Commit 1a5fe6fa9a729417eb9e6d558bb12f7503aefe2e

Authored by puhui999
1 parent 9bba1ce8

CRM: 完善客户、联系人、合同、回款计划、回款的操作日志

Showing 13 changed files with 255 additions and 163 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
1 1 package cn.iocoder.yudao.module.crm.enums;
2 2  
  3 +import static cn.iocoder.yudao.module.crm.enums.operatelog.CrmParseFunctionNameConstants.GET_CONTRACT_BY_ID;
  4 +
3 5 /**
4 6 * CRM 操作日志枚举
5 7 * 目的:统一管理,也减少 Service 里各种“复杂”字符串
... ... @@ -22,9 +24,9 @@ public interface LogRecordConstants {
22 24 String CRM_CUSTOMER_DELETE_SUB_TYPE = "删除客户";
23 25 String CRM_CUSTOMER_DELETE_SUCCESS = "删除了客户【{{#customerName}}】";
24 26 String CRM_CUSTOMER_TRANSFER_SUB_TYPE = "转移客户";
25   - String CRM_CUSTOMER_TRANSFER_SUCCESS = "将客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
26   - String CRM_CUSTOMER_LOCK_SUB_TYPE = "{{#crmCustomer.lockStatus ? '解锁客户' : '锁定客户'}}";
27   - String CRM_CUSTOMER_LOCK_SUCCESS = "{{#crmCustomer.lockStatus ? '将客户【' + #crmCustomer.name + '】解锁' : '将客户【' + #crmCustomer.name + '】锁定'}}";
  27 + String CRM_CUSTOMER_TRANSFER_SUCCESS = "将客户【{{#customer.name}}】的负责人从【{getAdminUserById{#customer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  28 + String CRM_CUSTOMER_LOCK_SUB_TYPE = "{{#customer.lockStatus ? '解锁客户' : '锁定客户'}}";
  29 + String CRM_CUSTOMER_LOCK_SUCCESS = "{{#customer.lockStatus ? '将客户【' + #customer.name + '】解锁' : '将客户【' + #customer.name + '】锁定'}}";
28 30 String CRM_CUSTOMER_POOL_SUB_TYPE = "客户放入公海";
29 31 String CRM_CUSTOMER_POOL_SUCCESS = "将客户【{{#customerName}}】放入了公海";
30 32 String CRM_CUSTOMER_RECEIVE_SUB_TYPE = "{{#ownerUserName != null ? '分配客户' : '领取客户'}}";
... ... @@ -49,14 +51,40 @@ public interface LogRecordConstants {
49 51 // ======================= CRM_CONTACT 联系人 =======================
50 52  
51 53 String CRM_CONTACT_TYPE = "CRM 联系人";
  54 + String CRM_CONTACT_CREATE_SUB_TYPE = "创建联系人";
  55 + String CRM_CONTACT_CREATE_SUCCESS = "创建了联系人{{#contact.name}}";
  56 + String CRM_CONTACT_UPDATE_SUB_TYPE = "更新联系人";
  57 + String CRM_CONTACT_UPDATE_SUCCESS = "更新了联系人【{{#contactName}}】: {_DIFF{#updateReqVO}}";
  58 + String CRM_CONTACT_DELETE_SUB_TYPE = "删除联系人";
  59 + String CRM_CONTACT_DELETE_SUCCESS = "删除了联系人【{{#contactName}}】";
  60 + String CRM_CONTACT_TRANSFER_SUB_TYPE = "转移联系人";
  61 + String CRM_CONTACT_TRANSFER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  62 +
52 63  
53 64 // ======================= CRM_BUSINESS 商机 =======================
54 65  
55 66 String CRM_BUSINESS_TYPE = "CRM 商机";
  67 + String CRM_BUSINESS_CREATE_SUB_TYPE = "创建商机";
  68 + String CRM_BUSINESS_CREATE_SUCCESS = "创建了商机{{#business.name}}";
  69 + String CRM_BUSINESS_UPDATE_SUB_TYPE = "更新商机";
  70 + String CRM_BUSINESS_UPDATE_SUCCESS = "更新了商机【{{#businessName}}】: {_DIFF{#updateReqVO}}";
  71 + String CRM_BUSINESS_DELETE_SUB_TYPE = "删除商机";
  72 + String CRM_BUSINESS_DELETE_SUCCESS = "删除了商机【{{#businessName}}】";
  73 + String CRM_BUSINESS_TRANSFER_SUB_TYPE = "转移商机";
  74 + String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
56 75  
57 76 // ======================= CRM_CONTRACT 合同 =======================
58 77  
59 78 String CRM_CONTRACT_TYPE = "CRM 合同";
  79 + String CRM_CONTRACT_CREATE_SUB_TYPE = "创建合同";
  80 + String CRM_CONTRACT_CREATE_SUCCESS = "创建了合同{{#contract.name}}";
  81 + String CRM_CONTRACT_UPDATE_SUB_TYPE = "更新合同";
  82 + String CRM_CONTRACT_UPDATE_SUCCESS = "更新了合同【{{#contractName}}】: {_DIFF{#updateReqVO}}";
  83 + String CRM_CONTRACT_DELETE_SUB_TYPE = "删除合同";
  84 + String CRM_CONTRACT_DELETE_SUCCESS = "删除了合同【{{#contractName}}】";
  85 + String CRM_CONTRACT_TRANSFER_SUB_TYPE = "转移合同";
  86 + String CRM_CONTRACT_TRANSFER_SUCCESS = "将合同【{{#contract.name}}】的负责人从【{getAdminUserById{#contract.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  87 +
60 88  
61 89 // ======================= CRM_PRODUCT 产品 =======================
62 90  
... ... @@ -79,9 +107,21 @@ public interface LogRecordConstants {
79 107 // ======================= CRM_RECEIVABLE 回款 =======================
80 108  
81 109 String CRM_RECEIVABLE_TYPE = "CRM 回款";
  110 + String CRM_RECEIVABLE_CREATE_SUB_TYPE = "创建回款";
  111 + String CRM_RECEIVABLE_CREATE_SUCCESS = "创建了合同【{" + GET_CONTRACT_BY_ID + "{#receivable.contractId}}】的第【{{#receivable.period}}】期回款";
  112 + String CRM_RECEIVABLE_UPDATE_SUB_TYPE = "更新回款";
  113 + String CRM_RECEIVABLE_UPDATE_SUCCESS = "更新了合同【{" + GET_CONTRACT_BY_ID + "{#receivable.contractId}}】的第【{{#receivable.period}}】期回款: {_DIFF{#updateReqVO}}";
  114 + String CRM_RECEIVABLE_DELETE_SUB_TYPE = "删除回款";
  115 + String CRM_RECEIVABLE_DELETE_SUCCESS = "删除了合同【{" + GET_CONTRACT_BY_ID + "{#receivable.contractId}}】的第【{{#receivable.period}}】期回款";
82 116  
83 117 // ======================= CRM_RECEIVABLE_PLAN 回款计划 =======================
84 118  
85 119 String CRM_RECEIVABLE_PLAN_TYPE = "CRM 回款计划";
  120 + String CRM_RECEIVABLE_PLAN_CREATE_SUB_TYPE = "创建回款计划";
  121 + String CRM_RECEIVABLE_PLAN_CREATE_SUCCESS = "创建了合同【{" + GET_CONTRACT_BY_ID + "{#receivablePlan.contractId}}】的第【{{#receivablePlan.period}}】期回款计划";
  122 + String CRM_RECEIVABLE_PLAN_UPDATE_SUB_TYPE = "更新回款计划";
  123 + String CRM_RECEIVABLE_PLAN_UPDATE_SUCCESS = "更新了合同【{" + GET_CONTRACT_BY_ID + "{#receivablePlan.contractId}}】的第【{{#receivablePlan.period}}】期回款计划: {_DIFF{#updateReqVO}}";
  124 + String CRM_RECEIVABLE_PLAN_DELETE_SUB_TYPE = "删除回款计划";
  125 + String CRM_RECEIVABLE_PLAN_DELETE_SUCCESS = "删除了合同【{" + GET_CONTRACT_BY_ID + "{#receivablePlan.contractId}}】的第【{{#receivablePlan.period}}】期回款计划";
86 126  
87 127 }
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/operatelog/CrmParseFunctionNameConstants.java
... ... @@ -13,5 +13,6 @@ public interface CrmParseFunctionNameConstants {
13 13 String GET_CUSTOMER_INDUSTRY = "getCustomerIndustry"; // 获取客户行业信息
14 14 String GET_CUSTOMER_LEVEL = "getCustomerLevel"; // 获取客户级别
15 15 String GET_CUSTOMER_SOURCE = "getCustomerSource"; // 获取客户来源
  16 + String GET_CONTRACT_BY_ID = "getContractById"; // 获取合同信息
16 17  
17 18 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
... ... @@ -7,7 +7,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
9 9 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
10   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.*;
  10 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
  12 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
11 14 import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert;
12 15 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
13 16 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
... ... @@ -59,7 +62,7 @@ public class CrmReceivableController {
59 62 @Operation(summary = "创建回款")
60 63 @PreAuthorize("@ss.hasPermission('crm:receivable:create')")
61 64 public CommonResult<Long> createReceivable(@Valid @RequestBody CrmReceivableCreateReqVO createReqVO) {
62   - return success(receivableService.createReceivable(createReqVO));
  65 + return success(receivableService.createReceivable(createReqVO, getLoginUserId()));
63 66 }
64 67  
65 68 @PutMapping("/update")
... ... @@ -141,12 +144,4 @@ public class CrmReceivableController {
141 144 return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList);
142 145 }
143 146  
144   - @PutMapping("/transfer")
145   - @Operation(summary = "回款转移")
146   - @PreAuthorize("@ss.hasPermission('crm:receivable:update')")
147   - public CommonResult<Boolean> transfer(@Valid @RequestBody CrmReceivableTransferReqVO reqVO) {
148   - receivableService.transferReceivable(reqVO, getLoginUserId());
149   - return success(true);
150   - }
151   -
152 147 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java
... ... @@ -7,7 +7,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
9 9 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
10   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.*;
  10 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
  12 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
11 14 import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert;
12 15 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
13 16 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
... ... @@ -148,12 +151,4 @@ public class CrmReceivablePlanController {
148 151 return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList);
149 152 }
150 153  
151   - @PutMapping("/transfer")
152   - @Operation(summary = "回款计划转移")
153   - @PreAuthorize("@ss.hasPermission('crm:receivable-plan:update')")
154   - public CommonResult<Boolean> transfer(@Valid @RequestBody CrmReceivablePlanTransferReqVO reqVO) {
155   - receivablePlanService.transferReceivablePlan(reqVO, getLoginUserId());
156   - return success(true);
157   - }
158   -
159 154 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.business;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 7 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO;
7 8 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
8 9 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
... ... @@ -17,6 +18,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
17 18 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
18 19 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
19 20 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  21 +import com.mzt.logapi.context.LogRecordContext;
  22 +import com.mzt.logapi.service.impl.DiffParseFunction;
  23 +import com.mzt.logapi.starter.annotation.LogRecord;
20 24 import jakarta.annotation.Resource;
21 25 import org.springframework.stereotype.Service;
22 26 import org.springframework.transaction.annotation.Transactional;
... ... @@ -28,6 +32,7 @@ import java.util.List;
28 32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
29 33 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
30 34 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
  35 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
31 36  
32 37 /**
33 38 * 商机 Service 实现类
... ... @@ -48,7 +53,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
48 53  
49 54 @Override
50 55 @Transactional(rollbackFor = Exception.class)
51   - // TODO @商机待定:操作日志;
  56 + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}",
  57 + success = CRM_BUSINESS_CREATE_SUCCESS)
52 58 public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) {
53 59 // 1. 插入商机
54 60 CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO);
... ... @@ -60,17 +66,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
60 66 // 2. 创建数据权限
61 67 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
62 68 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
  69 +
  70 + // 4. 记录操作日志上下文
  71 + LogRecordContext.putVariable("business", business);
63 72 return business.getId();
64 73 }
65 74  
66 75 @Override
67 76 @Transactional(rollbackFor = Exception.class)
68   - @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id",
69   - level = CrmPermissionLevelEnum.WRITE)
70   - // TODO @商机待定:操作日志;
  77 + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  78 + success = CRM_BUSINESS_UPDATE_SUCCESS)
  79 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
71 80 public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
72 81 // 1. 校验存在
73   - validateBusinessExists(updateReqVO.getId());
  82 + CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
74 83  
75 84 // 2. 更新商机
76 85 CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO);
... ... @@ -78,20 +87,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
78 87 // TODO 商机待定:插入商机与产品的关联表;校验商品存在
79 88  
80 89 // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
  90 + // 3. 记录操作日志上下文
  91 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessUpdateReqVO.class));
  92 + LogRecordContext.putVariable("businessName", oldBusiness.getName());
81 93 }
82 94  
83 95 @Override
84 96 @Transactional(rollbackFor = Exception.class)
  97 + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  98 + success = CRM_BUSINESS_DELETE_SUCCESS)
85 99 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
86 100 public void deleteBusiness(Long id) {
87 101 // 校验存在
88   - validateBusinessExists(id);
  102 + CrmBusinessDO business = validateBusinessExists(id);
89 103 // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段
90 104  
91 105 // 删除
92 106 businessMapper.deleteById(id);
93 107 // 删除数据权限
94 108 permissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id);
  109 +
  110 + // 记录操作日志上下文
  111 + LogRecordContext.putVariable("businessName", business.getName());
95 112 }
96 113  
97 114 private CrmBusinessDO validateBusinessExists(Long id) {
... ... @@ -102,6 +119,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
102 119 return crmBusiness;
103 120 }
104 121  
  122 +
  123 + @Override
  124 + @Transactional(rollbackFor = Exception.class)
  125 + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",
  126 + success = CRM_BUSINESS_TRANSFER_SUCCESS)
  127 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
  128 + public void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId) {
  129 + // 1 校验商机是否存在
  130 + CrmBusinessDO business = validateBusinessExists(reqVO.getId());
  131 +
  132 + // 2.1 数据权限转移
  133 + permissionService.transferPermission(
  134 + CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
  135 + // 2.2 设置新的负责人
  136 + businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
  137 +
  138 + // 记录操作日志上下文
  139 + LogRecordContext.putVariable("business", business);
  140 + }
  141 +
  142 + //======================= 查询相关 =======================
  143 +
105 144 @Override
106 145 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.READ)
107 146 public CrmBusinessDO getBusiness(Long id) {
... ... @@ -141,18 +180,4 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
141 180 convertSet(contactBusinessList, CrmContactBusinessDO::getBusinessId));
142 181 }
143 182  
144   - @Override
145   - @Transactional(rollbackFor = Exception.class)
146   - // TODO @puhui999:操作日志
147   - public void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId) {
148   - // 1 校验商机是否存在
149   - validateBusinessExists(reqVO.getId());
150   -
151   - // 2.1 数据权限转移
152   - permissionService.transferPermission(
153   - CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
154   - // 2.2 设置新的负责人
155   - businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
156   - }
157   -
158 183 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
... ... @@ -33,7 +33,7 @@ import java.util.List;
33 33  
34 34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
35 35 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
36   -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT_TYPE;
  36 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
37 37 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
38 38 import static java.util.Collections.singletonList;
39 39  
... ... @@ -65,7 +65,8 @@ public class CrmContactServiceImpl implements CrmContactService {
65 65  
66 66 @Override
67 67 @Transactional(rollbackFor = Exception.class)
68   - @LogRecord(type = CRM_CONTACT_TYPE, subType = "创建联系人", bizNo = "{{#contactId}}", success = "创建了联系人[{{#contactName}}]")
  68 + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_CREATE_SUB_TYPE, bizNo = "{{#contact.id}}",
  69 + success = CRM_CONTACT_CREATE_SUCCESS)
69 70 public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
70 71 // 1. 校验
71 72 validateRelationDataExists(createReqVO);
... ... @@ -86,18 +87,18 @@ public class CrmContactServiceImpl implements CrmContactService {
86 87 }
87 88  
88 89 // 5. 记录操作日志
89   - LogRecordContext.putVariable("contactId", contact.getId());
90   - LogRecordContext.putVariable("contactName", contact.getName());
  90 + LogRecordContext.putVariable("contact", contact);
91 91 return contact.getId();
92 92 }
93 93  
94 94 @Override
95 95 @Transactional(rollbackFor = Exception.class)
96   - @LogRecord(type = CRM_CONTACT_TYPE, subType = "更新联系人", bizNo = "{{#updateReqVO.id}}", success = "更新了联系人{_DIFF{#updateReqVO}}")
  96 + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  97 + success = CRM_CONTACT_UPDATE_SUCCESS)
97 98 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
98 99 public void updateContact(CrmContactSaveReqVO updateReqVO) {
99 100 // 1. 校验存在
100   - CrmContactDO contactDO = validateContactExists(updateReqVO.getId());
  101 + CrmContactDO oldContact = validateContactExists(updateReqVO.getId());
101 102 validateRelationDataExists(updateReqVO);
102 103  
103 104 // 2. 更新联系人
... ... @@ -105,7 +106,8 @@ public class CrmContactServiceImpl implements CrmContactService {
105 106 contactMapper.updateById(updateObj);
106 107  
107 108 // 3. 记录操作日志
108   - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contactDO, CrmContactSaveReqVO.class));
  109 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContact, CrmContactSaveReqVO.class));
  110 + LogRecordContext.putVariable("contactName", oldContact.getName());
109 111 }
110 112  
111 113 /**
... ... @@ -133,11 +135,13 @@ public class CrmContactServiceImpl implements CrmContactService {
133 135 }
134 136  
135 137 @Override
136   - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
137 138 @Transactional(rollbackFor = Exception.class)
  139 + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  140 + success = CRM_CONTACT_DELETE_SUCCESS)
  141 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
138 142 public void deleteContact(Long id) {
139 143 // 1.1 校验存在
140   - validateContactExists(id);
  144 + CrmContactDO contact = validateContactExists(id);
141 145 // 1.2 校验是否关联合同
142 146 if (contractService.getContractCountByContactId(id) > 0) {
143 147 throw exception(CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS);
... ... @@ -151,6 +155,9 @@ public class CrmContactServiceImpl implements CrmContactService {
151 155 // 4.2 删除商机关联
152 156 contactBusinessService.deleteContactBusinessByContactId(id);
153 157 // TODO @puhui999:删除跟进记录
  158 +
  159 + // 记录操作日志上下文
  160 + LogRecordContext.putVariable("contactName", contact.getName());
154 161 }
155 162  
156 163 private CrmContactDO validateContactExists(Long id) {
... ... @@ -162,6 +169,27 @@ public class CrmContactServiceImpl implements CrmContactService {
162 169 }
163 170  
164 171 @Override
  172 + @Transactional(rollbackFor = Exception.class)
  173 + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",
  174 + success = CRM_CONTACT_TRANSFER_SUCCESS)
  175 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
  176 + public void transferContact(CrmContactTransferReqVO reqVO, Long userId) {
  177 + // 1 校验联系人是否存在
  178 + CrmContactDO contact = validateContactExists(reqVO.getId());
  179 +
  180 + // 2.1 数据权限转移
  181 + permissionService.transferPermission(
  182 + CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
  183 + // 2.2 设置新的负责人
  184 + contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
  185 +
  186 + // 3. 记录转移日志
  187 + LogRecordContext.putVariable("contact", contact);
  188 + }
  189 +
  190 + //======================= 查询相关 =======================
  191 +
  192 + @Override
165 193 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.READ)
166 194 public CrmContactDO getContact(Long id) {
167 195 return contactMapper.selectById(id);
... ... @@ -191,20 +219,4 @@ public class CrmContactServiceImpl implements CrmContactService {
191 219 return contactMapper.selectPageByCustomerId(pageVO);
192 220 }
193 221  
194   - @Override
195   - // TODO @puhui999:权限校验
196   - // TODO @puhui999:记录操作日志;将联系人【名字】转移给【新负责人】
197   - public void transferContact(CrmContactTransferReqVO reqVO, Long userId) {
198   - // 1 校验联系人是否存在
199   - validateContactExists(reqVO.getId());
200   -
201   - // 2.1 数据权限转移
202   - permissionService.transferPermission(
203   - CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
204   - // 2.2 设置新的负责人
205   - contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
206   -
207   - // 3. TODO 记录转移日志
208   - }
209   -
210 222 }
211 223 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.contract;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
7 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
8 9 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
... ... @@ -15,6 +16,9 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
15 16 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
16 17 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
17 18 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  19 +import com.mzt.logapi.context.LogRecordContext;
  20 +import com.mzt.logapi.service.impl.DiffParseFunction;
  21 +import com.mzt.logapi.starter.annotation.LogRecord;
18 22 import jakarta.annotation.Resource;
19 23 import org.springframework.stereotype.Service;
20 24 import org.springframework.transaction.annotation.Transactional;
... ... @@ -25,6 +29,7 @@ import java.util.List;
25 29  
26 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
27 31 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
  32 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
28 33  
29 34 /**
30 35 * CRM 合同 Service 实现类
... ... @@ -42,7 +47,9 @@ public class CrmContractServiceImpl implements CrmContractService {
42 47 private CrmPermissionService crmPermissionService;
43 48  
44 49 @Override
45   - // TODO @puhui999:添加操作日志
  50 + @Transactional(rollbackFor = Exception.class)
  51 + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
  52 + success = CRM_CONTRACT_CREATE_SUCCESS)
46 53 public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) {
47 54 // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
48 55 // 插入合同
... ... @@ -53,38 +60,52 @@ public class CrmContractServiceImpl implements CrmContractService {
53 60 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
54 61 .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
55 62 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
  63 +
  64 + // 4. 记录操作日志上下文
  65 + LogRecordContext.putVariable("contract", contract);
56 66 return contract.getId();
57 67 }
58 68  
59 69 @Override
60 70 @Transactional(rollbackFor = Exception.class)
  71 + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  72 + success = CRM_CONTRACT_UPDATE_SUCCESS)
61 73 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
62   - // TODO @puhui999:添加操作日志
63 74 public void updateContract(CrmContractUpdateReqVO updateReqVO) {
64 75 // TODO @合同待定:只有草稿、审批中,可以编辑;
65 76 // 校验存在
66   - validateContractExists(updateReqVO.getId());
  77 + CrmContractDO oldContract = validateContractExists(updateReqVO.getId());
67 78 // 更新合同
68 79 CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO);
69 80 contractMapper.updateById(updateObj);
70 81 // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
  82 +
  83 + // 3. 记录操作日志上下文
  84 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractUpdateReqVO.class));
  85 + LogRecordContext.putVariable("contractName", oldContract.getName());
71 86 }
72 87  
73 88 // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
74 89  
75 90 // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum
76 91  
  92 +
77 93 @Override
78 94 @Transactional(rollbackFor = Exception.class)
  95 + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  96 + success = CRM_CONTRACT_DELETE_SUCCESS)
79 97 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
80 98 public void deleteContract(Long id) {
81 99 // TODO @合同待定:如果被 CrmReceivableDO 所使用,则不允许删除
82 100 // 校验存在
83   - validateContractExists(id);
  101 + CrmContractDO contract = validateContractExists(id);
84 102 // 删除
85 103 contractMapper.deleteById(id);
86 104 // 删除数据权限
87 105 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTRACT.getType(), id);
  106 +
  107 + // 记录操作日志上下文
  108 + LogRecordContext.putVariable("contractName", contract.getName());
88 109 }
89 110  
90 111 private CrmContractDO validateContractExists(Long id) {
... ... @@ -96,6 +117,27 @@ public class CrmContractServiceImpl implements CrmContractService {
96 117 }
97 118  
98 119 @Override
  120 + @Transactional(rollbackFor = Exception.class)
  121 + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",
  122 + success = CRM_CONTRACT_TRANSFER_SUCCESS)
  123 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
  124 + public void transferContract(CrmContractTransferReqVO reqVO, Long userId) {
  125 + // 1. 校验合同是否存在
  126 + CrmContractDO contract = validateContractExists(reqVO.getId());
  127 +
  128 + // 2.1 数据权限转移
  129 + crmPermissionService.transferPermission(
  130 + CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
  131 + // 2.2 设置负责人
  132 + contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
  133 +
  134 + // 3. 记录转移日志
  135 + LogRecordContext.putVariable("contract", contract);
  136 + }
  137 +
  138 + //======================= 查询相关 =======================
  139 +
  140 + @Override
99 141 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.READ)
100 142 public CrmContractDO getContract(Long id) {
101 143 return contractMapper.selectById(id);
... ... @@ -121,21 +163,6 @@ public class CrmContractServiceImpl implements CrmContractService {
121 163 }
122 164  
123 165 @Override
124   - @Transactional(rollbackFor = Exception.class)
125   - // 3. TODO @puhui999:记录转移日志
126   - // TODO @puhui999:权限校验,这里要搞哇?
127   - public void transferContract(CrmContractTransferReqVO reqVO, Long userId) {
128   - // 1. 校验合同是否存在
129   - validateContractExists(reqVO.getId());
130   -
131   - // 2.1 数据权限转移
132   - crmPermissionService.transferPermission(
133   - CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
134   - // 2.2 设置负责人
135   - contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
136   - }
137   -
138   - @Override
139 166 public Long getContractCountByContactId(Long contactId) {
140 167 return contractMapper.selectCountByContactId(contactId);
141 168 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
... ... @@ -145,10 +145,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
145 145 // 2.2 转移后重新设置负责人
146 146 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
147 147  
148   - // 3. TODO 记录转移日志
149   - // 记录操作日志上下文
150   - // TODO @puhui999:crmCustomer=》customer,也看看其他有没类似的情况哈
151   - LogRecordContext.putVariable("crmCustomer", customer);
  148 + // 3. 记录转移日志
  149 + LogRecordContext.putVariable("customer", customer);
152 150 }
153 151  
154 152 @Override
... ... @@ -172,7 +170,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
172 170  
173 171 // 3. 记录操作日志上下文
174 172 // tips: 因为这里使用的是老的状态所以记录时反着记录,也就是 lockStatus 为 true 那么就是解锁反之为锁定
175   - LogRecordContext.putVariable("crmCustomer", customer);
  173 + LogRecordContext.putVariable("customer", customer);
176 174 }
177 175  
178 176 // ==================== 公海相关操作 ====================
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.receivable;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
5 5 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
7 6 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
8 7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
9 8 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
... ... @@ -78,12 +77,4 @@ public interface CrmReceivablePlanService {
78 77 */
79 78 PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
80 79  
81   - /**
82   - * 回款计划转移
83   - *
84   - * @param reqVO 请求
85   - * @param userId 用户编号
86   - */
87   - void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId);
88   -
89 80 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
... ... @@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
5 5 import cn.hutool.core.util.ObjectUtil;
6 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 8 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
8 9 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
9   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
10 10 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
11 11 import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert;
12 12 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
... ... @@ -20,6 +20,9 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
20 20 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
21 21 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
22 22 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  23 +import com.mzt.logapi.context.LogRecordContext;
  24 +import com.mzt.logapi.service.impl.DiffParseFunction;
  25 +import com.mzt.logapi.starter.annotation.LogRecord;
23 26 import jakarta.annotation.Resource;
24 27 import org.springframework.stereotype.Service;
25 28 import org.springframework.validation.annotation.Validated;
... ... @@ -29,6 +32,7 @@ import java.util.List;
29 32  
30 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 34 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
  35 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
32 36  
33 37 // TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈;
34 38  
... ... @@ -49,10 +53,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
49 53 @Resource
50 54 private CrmCustomerService customerService;
51 55 @Resource
52   - private CrmPermissionService crmPermissionService;
  56 + private CrmPermissionService permissionService;
53 57  
54 58 @Override
55   - // TODO @puhui999:操作日志
  59 + @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_CREATE_SUB_TYPE, bizNo = "{{#receivablePlan.id}}",
  60 + success = CRM_RECEIVABLE_PLAN_CREATE_SUCCESS)
56 61 public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) {
57 62 // TODO @liuhongfeng:第几期的计算;基于是 contractId + contractDO 的第几个还款
58 63 // TODO @liuhongfeng contractId:校验合同是否存在
... ... @@ -64,9 +69,12 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
64 69  
65 70 receivablePlanMapper.insert(receivablePlan);
66 71 // 创建数据权限
67   - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
  72 + permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
68 73 .setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()).setBizId(receivablePlan.getId())
69 74 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
  75 +
  76 + // 4. 记录操作日志上下文
  77 + LogRecordContext.putVariable("receivablePlan", receivablePlan);
70 78 return receivablePlan.getId();
71 79 }
72 80  
... ... @@ -89,31 +97,44 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
89 97 }
90 98  
91 99 @Override
  100 + @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  101 + success = CRM_RECEIVABLE_PLAN_UPDATE_SUCCESS)
92 102 @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
93   - // TODO @puhui999:操作日志
94 103 public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) {
95 104 // TODO @liuhongfeng:如果已经有对应的还款,则不允许编辑;
96 105 // 校验存在
97   - validateReceivablePlanExists(updateReqVO.getId());
  106 + CrmReceivablePlanDO oldReceivablePlan = validateReceivablePlanExists(updateReqVO.getId());
98 107  
99 108 // 更新
100 109 CrmReceivablePlanDO updateObj = CrmReceivablePlanConvert.INSTANCE.convert(updateReqVO);
101 110 receivablePlanMapper.updateById(updateObj);
  111 +
  112 + // 3. 记录操作日志上下文
  113 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanUpdateReqVO.class));
  114 + LogRecordContext.putVariable("receivablePlan", oldReceivablePlan);
102 115 }
103 116  
104 117 @Override
  118 + @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  119 + success = CRM_RECEIVABLE_PLAN_DELETE_SUCCESS)
105 120 @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
106 121 public void deleteReceivablePlan(Long id) {
107 122 // 校验存在
108   - validateReceivablePlanExists(id);
  123 + CrmReceivablePlanDO receivablePlan = validateReceivablePlanExists(id);
109 124 // 删除
110 125 receivablePlanMapper.deleteById(id);
  126 + // 删除数据权限
  127 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
  128 + // 记录操作日志上下文
  129 + LogRecordContext.putVariable("receivablePlan", receivablePlan);
111 130 }
112 131  
113   - private void validateReceivablePlanExists(Long id) {
114   - if (receivablePlanMapper.selectById(id) == null) {
  132 + private CrmReceivablePlanDO validateReceivablePlanExists(Long id) {
  133 + CrmReceivablePlanDO receivablePlan = receivablePlanMapper.selectById(id);
  134 + if (receivablePlan == null) {
115 135 throw exception(RECEIVABLE_PLAN_NOT_EXISTS);
116 136 }
  137 + return receivablePlan;
117 138 }
118 139  
119 140 @Override
... ... @@ -141,19 +162,4 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
141 162 return receivablePlanMapper.selectPageByCustomerId(pageReqVO);
142 163 }
143 164  
144   - // TODO @puhui999:这个没有 transfer 接口;可能是的哈
145   - @Override
146   - public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) {
147   - // 1 校验回款计划是否存在
148   - validateReceivablePlanExists(reqVO.getId());
149   -
150   - // 2.1 数据权限转移
151   - crmPermissionService.transferPermission(
152   - CrmReceivablePlanConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()));
153   - // 2.2 设置新的负责人
154   - receivablePlanMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
155   -
156   - // 3. TODO 记录转移日志
157   - }
158   -
159 165 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.receivable;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
5 5 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
7 6 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
8 7 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
9 8 import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
... ... @@ -23,9 +22,10 @@ public interface CrmReceivableService {
23 22 * 创建回款
24 23 *
25 24 * @param createReqVO 创建信息
  25 + * @param userId 用户编号
26 26 * @return 编号
27 27 */
28   - Long createReceivable(@Valid CrmReceivableCreateReqVO createReqVO);
  28 + Long createReceivable(@Valid CrmReceivableCreateReqVO createReqVO, Long userId);
29 29  
30 30 /**
31 31 * 更新回款
... ... @@ -78,12 +78,4 @@ public interface CrmReceivableService {
78 78 */
79 79 PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO);
80 80  
81   - /**
82   - * 回款转移
83   - *
84   - * @param reqVO 请求
85   - * @param userId 用户编号
86   - */
87   - void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId);
88   -
89 81 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
... ... @@ -5,9 +5,9 @@ import cn.hutool.core.collection.ListUtil;
5 5 import cn.hutool.core.util.ObjectUtil;
6 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 9 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
9 10 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
10   -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
11 11 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
12 12 import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert;
13 13 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
... ... @@ -22,6 +22,10 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
22 22 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
23 23 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
24 24 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
  25 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  26 +import com.mzt.logapi.context.LogRecordContext;
  27 +import com.mzt.logapi.service.impl.DiffParseFunction;
  28 +import com.mzt.logapi.starter.annotation.LogRecord;
25 29 import jakarta.annotation.Resource;
26 30 import org.springframework.stereotype.Service;
27 31 import org.springframework.validation.annotation.Validated;
... ... @@ -31,6 +35,7 @@ import java.util.List;
31 35  
32 36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
33 37 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
  38 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
34 39  
35 40 /**
36 41 * CRM 回款 Service 实现类
... ... @@ -51,11 +56,12 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
51 56 @Resource
52 57 private CrmReceivablePlanService receivablePlanService;
53 58 @Resource
54   - private CrmPermissionService crmPermissionService;
  59 + private CrmPermissionService permissionService;
55 60  
56 61 @Override
57   - // TODO @puhui999:操作日志
58   - public Long createReceivable(CrmReceivableCreateReqVO createReqVO) {
  62 + @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}",
  63 + success = CRM_RECEIVABLE_CREATE_SUCCESS)
  64 + public Long createReceivable(CrmReceivableCreateReqVO createReqVO, Long userId) {
59 65 // 插入还款
60 66 CrmReceivableDO receivable = CrmReceivableConvert.INSTANCE.convert(createReqVO);
61 67 if (ObjectUtil.isNull(receivable.getAuditStatus())) {
... ... @@ -67,8 +73,12 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
67 73 checkReceivable(receivable);
68 74  
69 75 receivableMapper.insert(receivable);
70   -
  76 + // 3. 创建数据权限
  77 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType())
  78 + .setBizId(receivable.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
71 79 // TODO @liuhongfeng:需要更新关联的 plan
  80 + // 记录操作日志上下文
  81 + LogRecordContext.putVariable("receivable", receivable);
72 82 return receivable.getId();
73 83 }
74 84  
... ... @@ -98,11 +108,12 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
98 108 }
99 109  
100 110 @Override
101   - // TODO @puhui999:操作日志
102   - // TODO @puhui999:权限校验
  111 + @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  112 + success = CRM_RECEIVABLE_UPDATE_SUCCESS)
  113 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
103 114 public void updateReceivable(CrmReceivableUpdateReqVO updateReqVO) {
104 115 // 校验存在
105   - validateReceivableExists(updateReqVO.getId());
  116 + CrmReceivableDO oldReceivable = validateReceivableExists(updateReqVO.getId());
106 117 // TODO @liuhongfeng:只有在草稿、审核中,可以提交修改
107 118  
108 119 // 更新还款
... ... @@ -110,6 +121,9 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
110 121 receivableMapper.updateById(updateObj);
111 122  
112 123 // TODO @liuhongfeng:需要更新关联的 plan
  124 + // 3. 记录操作日志上下文
  125 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivable, CrmReceivableUpdateReqVO.class));
  126 + LogRecordContext.putVariable("receivable", oldReceivable);
113 127 }
114 128  
115 129 // TODO @liuhongfeng:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
... ... @@ -117,24 +131,33 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
117 131 // TODO @liuhongfeng:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum
118 132  
119 133 @Override
120   - // TODO @puhui999:操作日志
121   - // TODO @puhui999:权限校验
  134 + @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  135 + success = CRM_RECEIVABLE_DELETE_SUCCESS)
  136 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
122 137 public void deleteReceivable(Long id) {
123 138 // TODO @liuhongfeng:如果被 CrmReceivablePlanDO 所使用,则不允许删除
124 139 // 校验存在
125   - validateReceivableExists(id);
  140 + CrmReceivableDO receivable = validateReceivableExists(id);
126 141 // 删除
127 142 receivableMapper.deleteById(id);
  143 +
  144 + // 删除数据权限
  145 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
  146 +
  147 + // 记录操作日志上下文
  148 + LogRecordContext.putVariable("receivable", receivable);
128 149 }
129 150  
130   - private void validateReceivableExists(Long id) {
131   - if (receivableMapper.selectById(id) == null) {
  151 + private CrmReceivableDO validateReceivableExists(Long id) {
  152 + CrmReceivableDO receivable = receivableMapper.selectById(id);
  153 + if (receivable == null) {
132 154 throw exception(RECEIVABLE_NOT_EXISTS);
133 155 }
  156 + return receivable;
134 157 }
135 158  
136   - // TODO @芋艿:数据权限
137 159 @Override
  160 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.READ)
138 161 public CrmReceivableDO getReceivable(Long id) {
139 162 return receivableMapper.selectById(id);
140 163 }
... ... @@ -158,18 +181,4 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
158 181 return receivableMapper.selectPageByCustomerId(pageReqVO);
159 182 }
160 183  
161   - @Override
162   - public void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId) {
163   - // 1 校验回款是否存在
164   - validateReceivableExists(reqVO.getId());
165   -
166   - // 2.1 数据权限转移
167   - crmPermissionService.transferPermission(
168   - CrmReceivableConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()));
169   - // 2.2 设置新的负责人
170   - receivableMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
171   -
172   - // 3. TODO 记录转移日志
173   - }
174   -
175 184 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java
... ... @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
13 13 import org.springframework.context.annotation.Import;
14 14  
15 15 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  16 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
16 17 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
17 18 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
18 19 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
... ... @@ -42,7 +43,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest {
42 43 CrmReceivableCreateReqVO reqVO = randomPojo(CrmReceivableCreateReqVO.class);
43 44  
44 45 // 调用
45   - Long receivableId = receivableService.createReceivable(reqVO);
  46 + Long receivableId = receivableService.createReceivable(reqVO, getLoginUserId());
46 47 // 断言
47 48 assertNotNull(receivableId);
48 49 // 校验记录的属性是否正确
... ...