Commit bada32750c67282ff7f8c8b1acbad736c3448c28
Committed by
Gitee
!795 CRM: 完善线索、商机、联系人、客户、合同、回款、回款计划数据权限
Merge pull request !795 from puhui999/develop
Showing
76 changed files
with
1455 additions
and
310 deletions
yudao-dependencies/pom.xml
| ... | ... | @@ -62,6 +62,7 @@ |
| 62 | 62 | <jsch.version>0.1.55</jsch.version> |
| 63 | 63 | <tika-core.version>2.9.1</tika-core.version> |
| 64 | 64 | <ip2region.version>2.7.0</ip2region.version> |
| 65 | + <bizlog-sdk.version>3.0.6</bizlog-sdk.version> | |
| 65 | 66 | <!-- 三方云服务相关 --> |
| 66 | 67 | <okio.version>3.5.0</okio.version> |
| 67 | 68 | <okhttp3.version>4.11.0</okhttp3.version> |
| ... | ... | @@ -100,6 +101,17 @@ |
| 100 | 101 | <version>${revision}</version> |
| 101 | 102 | </dependency> |
| 102 | 103 | <dependency> |
| 104 | + <groupId>io.github.mouzt</groupId> | |
| 105 | + <artifactId>bizlog-sdk</artifactId> | |
| 106 | + <version>${bizlog-sdk.version}</version> | |
| 107 | + <exclusions> | |
| 108 | + <exclusion> <!-- 排除掉springboot依赖使用项目的 --> | |
| 109 | + <groupId>org.springframework.boot</groupId> | |
| 110 | + <artifactId>spring-boot-starter</artifactId> | |
| 111 | + </exclusion> | |
| 112 | + </exclusions> | |
| 113 | + </dependency> | |
| 114 | + <dependency> | |
| 103 | 115 | <groupId>cn.iocoder.boot</groupId> |
| 104 | 116 | <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> |
| 105 | 117 | <version>${revision}</version> | ... | ... |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java
| ... | ... | @@ -177,4 +177,14 @@ public class DateUtils { |
| 177 | 177 | return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now()); |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | + /** | |
| 181 | + * 是否昨天 | |
| 182 | + * | |
| 183 | + * @param date 日期 | |
| 184 | + * @return 是否 | |
| 185 | + */ | |
| 186 | + public static boolean isYesterday(LocalDateTime date) { | |
| 187 | + return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now().minusDays(1)); | |
| 188 | + } | |
| 189 | + | |
| 180 | 190 | } | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.enums; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * CRM 操作日志枚举 | |
| 5 | + * | |
| 6 | + * @author HUIHUI | |
| 7 | + */ | |
| 8 | +public interface LogRecordConstants { | |
| 9 | + | |
| 10 | + //======================= 客户模块类型 ======================= | |
| 11 | + // TODO puhui999: 确保模块命名方式为 module + 子模块名称的方式。统一定义模块名称是为了方便查询各自记录的操作日志,列如说:查询客户【张三的操作日志】就可以 module + bizId | |
| 12 | + String CRM_LEADS = "CRM-线索"; | |
| 13 | + String CRM_CUSTOMER = "CRM-客户"; | |
| 14 | + String CRM_CONTACT = "CRM-联系人"; | |
| 15 | + String CRM_BUSINESS = "CRM-商机"; | |
| 16 | + String CRM_CONTRACT = "CRM-合同"; | |
| 17 | + String CRM_PRODUCT = "CRM-产品"; | |
| 18 | + String CRM_RECEIVABLE = "CRM-回款"; | |
| 19 | + String CRM_RECEIVABLE_PLAN = "CRM-回款计划"; | |
| 20 | + | |
| 21 | + //======================= 客户转移操作日志 ======================= | |
| 22 | + | |
| 23 | + String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; | |
| 24 | + String TRANSFER_CUSTOMER_LOG_FAIL = ""; | |
| 25 | + | |
| 26 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
| ... | ... | @@ -22,7 +22,9 @@ public enum CrmBizTypeEnum implements IntArrayValuable { |
| 22 | 22 | CRM_CONTACT(3, "联系人"), |
| 23 | 23 | CRM_BUSINESS(4, "商机"), |
| 24 | 24 | CRM_CONTRACT(5, "合同"), |
| 25 | - CRM_PRODUCT(6, "产品") | |
| 25 | + CRM_PRODUCT(6, "产品"), | |
| 26 | + CRM_RECEIVABLE(7, "回款"), | |
| 27 | + CRM_RECEIVABLE_PLAN(8, "回款计划") | |
| 26 | 28 | ; |
| 27 | 29 | |
| 28 | 30 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray(); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/pom.xml
| ... | ... | @@ -60,6 +60,10 @@ |
| 60 | 60 | <groupId>cn.iocoder.boot</groupId> |
| 61 | 61 | <artifactId>yudao-spring-boot-starter-excel</artifactId> |
| 62 | 62 | </dependency> |
| 63 | + <dependency> | |
| 64 | + <groupId>cn.iocoder.boot</groupId> | |
| 65 | + <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | |
| 66 | + </dependency> | |
| 63 | 67 | |
| 64 | 68 | <!-- Test 测试相关 --> |
| 65 | 69 | <dependency> | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
| ... | ... | @@ -122,7 +122,7 @@ public class CrmBusinessController { |
| 122 | 122 | @Operation(summary = "获得商机分页,基于指定客户") |
| 123 | 123 | public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { |
| 124 | 124 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 125 | - PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomer(pageReqVO, getLoginUserId()); | |
| 125 | + PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); | |
| 126 | 126 | // 处理客户名称回显 |
| 127 | 127 | // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; |
| 128 | 128 | Set<Long> customerIds = pageResult.getList().stream() | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java
| ... | ... | @@ -24,7 +24,4 @@ public class CrmBusinessPageReqVO extends PageParam { |
| 24 | 24 | @InEnum(CrmSceneTypeEnum.class) |
| 25 | 25 | private Integer sceneType; // 场景类型,为 null 时则表示全部 |
| 26 | 26 | |
| 27 | - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | |
| 28 | - private Boolean pool; // null 则表示为不是公海数据 | |
| 29 | - | |
| 30 | 27 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java
| ... | ... | @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 4 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import lombok.Data; | |
| 6 | - | |
| 7 | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | |
| 8 | 7 | |
| 9 | 8 | @Schema(description = "管理后台 - 商机转移 Request VO") |
| 10 | 9 | @Data |
| 11 | 10 | public class CrmBusinessTransferReqVO { |
| 12 | 11 | |
| 13 | 12 | @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 14 | - @NotNull(message = "联系人编号不能为空") | |
| 13 | + @NotNull(message = "商机编号不能为空") | |
| 15 | 14 | private Long id; |
| 16 | 15 | |
| 17 | 16 | /** | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
| ... | ... | @@ -88,4 +88,12 @@ public class CrmClueController { |
| 88 | 88 | ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | + @PutMapping("/transfer") | |
| 92 | + @Operation(summary = "线索转移") | |
| 93 | + @PreAuthorize("@ss.hasPermission('crm:clue:update')") | |
| 94 | + public CommonResult<Boolean> transfer(@Valid @RequestBody CrmClueTransferReqVO reqVO) { | |
| 95 | + clueService.transferClue(reqVO, getLoginUserId()); | |
| 96 | + return success(true); | |
| 97 | + } | |
| 98 | + | |
| 91 | 99 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - 线索转移 Request VO") | |
| 9 | +@Data | |
| 10 | +public class CrmClueTransferReqVO { | |
| 11 | + | |
| 12 | + @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 13 | + @NotNull(message = "线索编号不能为空") | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 新负责人的用户编号 | |
| 18 | + */ | |
| 19 | + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 20 | + @NotNull(message = "新负责人的用户编号不能为空") | |
| 21 | + private Long newOwnerUserId; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 老负责人加入团队后的权限级别。如果 null 说明移除 | |
| 25 | + * | |
| 26 | + * 关联 {@link CrmPermissionLevelEnum} | |
| 27 | + */ | |
| 28 | + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 29 | + private Integer oldOwnerPermissionLevel; | |
| 30 | + | |
| 31 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
| ... | ... | @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 9 | 9 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 10 | 10 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 11 | 11 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; |
| 12 | -import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; | |
| 12 | +import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; | |
| 13 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 14 | 14 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 15 | 15 | import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; |
| ... | ... | @@ -100,7 +100,7 @@ public class CrmContactController { |
| 100 | 100 | // 3. 直属上级 |
| 101 | 101 | List<CrmContactDO> parentContactList = contactService.getContactList( |
| 102 | 102 | Collections.singletonList(contact.getParentId()), getLoginUserId()); |
| 103 | - return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); | |
| 103 | + return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | @GetMapping("/simple-all-list") |
| ... | ... | @@ -110,7 +110,7 @@ public class CrmContactController { |
| 110 | 110 | CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); |
| 111 | 111 | pageReqVO.setPageSize(PAGE_SIZE_NONE); |
| 112 | 112 | List<CrmContactDO> list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList(); |
| 113 | - return success(ContactConvert.INSTANCE.convertAllList(list)); | |
| 113 | + return success(CrmContactConvert.INSTANCE.convertAllList(list)); | |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | @GetMapping("/page") |
| ... | ... | @@ -125,7 +125,7 @@ public class CrmContactController { |
| 125 | 125 | @Operation(summary = "获得联系人分页,基于指定客户") |
| 126 | 126 | public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { |
| 127 | 127 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); |
| 128 | - PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO, getLoginUserId()); | |
| 128 | + PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO); | |
| 129 | 129 | return success(convertDetailContactPage(pageResult)); |
| 130 | 130 | } |
| 131 | 131 | |
| ... | ... | @@ -161,7 +161,15 @@ public class CrmContactController { |
| 161 | 161 | // 3. 直属上级 |
| 162 | 162 | List<CrmContactDO> parentContactList = contactService.getContactList( |
| 163 | 163 | convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); |
| 164 | - return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); | |
| 164 | + return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); | |
| 165 | + } | |
| 166 | + | |
| 167 | + @PutMapping("/transfer") | |
| 168 | + @Operation(summary = "联系人转移") | |
| 169 | + @PreAuthorize("@ss.hasPermission('crm:contact:update')") | |
| 170 | + public CommonResult<Boolean> transfer(@Valid @RequestBody CrmContactTransferReqVO reqVO) { | |
| 171 | + contactService.transferContact(reqVO, getLoginUserId()); | |
| 172 | + return success(true); | |
| 165 | 173 | } |
| 166 | 174 | |
| 167 | 175 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java
| ... | ... | @@ -39,7 +39,4 @@ public class CrmContactPageReqVO extends PageParam { |
| 39 | 39 | @InEnum(CrmSceneTypeEnum.class) |
| 40 | 40 | private Integer sceneType; // 场景类型,为 null 时则表示全部 |
| 41 | 41 | |
| 42 | - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | |
| 43 | - private Boolean pool; // null 则表示为不是公海数据 | |
| 44 | - | |
| 45 | 42 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
| ... | ... | @@ -8,7 +8,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 | 10 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; |
| 11 | -import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; | |
| 11 | +import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; | |
| 12 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 13 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 14 | 14 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| ... | ... | @@ -80,7 +80,7 @@ public class CrmContractController { |
| 80 | 80 | @PreAuthorize("@ss.hasPermission('crm:contract:query')") |
| 81 | 81 | public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) { |
| 82 | 82 | CrmContractDO contract = contractService.getContract(id); |
| 83 | - return success(ContractConvert.INSTANCE.convert(contract)); | |
| 83 | + return success(CrmContractConvert.INSTANCE.convert(contract)); | |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | @GetMapping("/page") |
| ... | ... | @@ -95,7 +95,7 @@ public class CrmContractController { |
| 95 | 95 | @Operation(summary = "获得联系人分页,基于指定客户") |
| 96 | 96 | public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { |
| 97 | 97 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); |
| 98 | - PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomer(pageVO, getLoginUserId()); | |
| 98 | + PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO); | |
| 99 | 99 | return success(convertDetailContractPage(pageResult)); |
| 100 | 100 | } |
| 101 | 101 | |
| ... | ... | @@ -108,7 +108,7 @@ public class CrmContractController { |
| 108 | 108 | PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); |
| 109 | 109 | // 导出 Excel |
| 110 | 110 | ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class, |
| 111 | - ContractConvert.INSTANCE.convertList02(pageResult.getList())); | |
| 111 | + CrmContractConvert.INSTANCE.convertList02(pageResult.getList())); | |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | /** |
| ... | ... | @@ -128,7 +128,7 @@ public class CrmContractController { |
| 128 | 128 | // 2. 获取创建人、负责人列表 |
| 129 | 129 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, |
| 130 | 130 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); |
| 131 | - return ContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); | |
| 131 | + return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); | |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | @PutMapping("/transfer") | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java
| ... | ... | @@ -30,7 +30,4 @@ public class CrmContractPageReqVO extends PageParam { |
| 30 | 30 | @InEnum(CrmSceneTypeEnum.class) |
| 31 | 31 | private Integer sceneType; // 场景类型,为 null 时则表示全部 |
| 32 | 32 | |
| 33 | - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | |
| 34 | - private Boolean pool; // null 则表示为不是公海数据 TODO @puhui999:合同没有公海。目前只有【客户】【线索】有公海,其它都没 | |
| 35 | - | |
| 36 | 33 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http
| 1 | -### 请求 /update | |
| 2 | -GET {{baseUrl}}/crm/customer/page?pageNo=1&pageSize=10&name="张三" | |
| 1 | +### 请求 /transfer | |
| 2 | +PUT {{baseUrl}}/crm/customer/transfer | |
| 3 | +Content-Type: application/json | |
| 3 | 4 | Authorization: Bearer {{token}} |
| 4 | 5 | tenant-id: {{adminTenentId}} |
| 5 | 6 | |
| 7 | +{ | |
| 8 | + "id": 10, | |
| 9 | + "newOwnerUserId": 127 | |
| 10 | +} | |
| 6 | 11 | |
| 12 | +### 自定义日志记录结果 | |
| 13 | +### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9)) | |
| 14 | + | |
| 15 | +### diff 日志 | |
| 16 | +### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36) | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
| ... | ... | @@ -11,20 +11,22 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 11 | 11 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 12 | 12 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 13 | 13 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 14 | +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | |
| 15 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | |
| 14 | 16 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 15 | 17 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 16 | 18 | import io.swagger.v3.oas.annotations.Operation; |
| 17 | 19 | import io.swagger.v3.oas.annotations.Parameter; |
| 18 | 20 | import io.swagger.v3.oas.annotations.Parameters; |
| 19 | 21 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 22 | +import jakarta.annotation.Resource; | |
| 23 | +import jakarta.servlet.http.HttpServletResponse; | |
| 24 | +import jakarta.validation.Valid; | |
| 20 | 25 | import org.mapstruct.ap.internal.util.Collections; |
| 21 | 26 | import org.springframework.security.access.prepost.PreAuthorize; |
| 22 | 27 | import org.springframework.validation.annotation.Validated; |
| 23 | 28 | import org.springframework.web.bind.annotation.*; |
| 24 | 29 | |
| 25 | -import jakarta.annotation.Resource; | |
| 26 | -import jakarta.servlet.http.HttpServletResponse; | |
| 27 | -import jakarta.validation.Valid; | |
| 28 | 30 | import java.io.IOException; |
| 29 | 31 | import java.util.List; |
| 30 | 32 | import java.util.Map; |
| ... | ... | @@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 36 | 38 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; |
| 37 | 39 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 38 | 40 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 41 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | |
| 39 | 42 | |
| 40 | 43 | @Tag(name = "管理后台 - CRM 客户") |
| 41 | 44 | @RestController |
| ... | ... | @@ -50,6 +53,8 @@ public class CrmCustomerController { |
| 50 | 53 | private DeptApi deptApi; |
| 51 | 54 | @Resource |
| 52 | 55 | private AdminUserApi adminUserApi; |
| 56 | + @Resource | |
| 57 | + private OperateLogApi operateLogApi; | |
| 53 | 58 | |
| 54 | 59 | @PostMapping("/create") |
| 55 | 60 | @Operation(summary = "创建客户") |
| ... | ... | @@ -59,7 +64,7 @@ public class CrmCustomerController { |
| 59 | 64 | } |
| 60 | 65 | |
| 61 | 66 | @PutMapping("/update") |
| 62 | - @Operation(summary = "更新客户") | |
| 67 | + //@Operation(summary = "更新客户") | |
| 63 | 68 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 64 | 69 | public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { |
| 65 | 70 | customerService.updateCustomer(updateReqVO); |
| ... | ... | @@ -123,13 +128,28 @@ public class CrmCustomerController { |
| 123 | 128 | } |
| 124 | 129 | |
| 125 | 130 | @PutMapping("/transfer") |
| 126 | - @Operation(summary = "客户转移") | |
| 131 | + //@Operation(summary = "客户转移") | |
| 127 | 132 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 128 | 133 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { |
| 129 | 134 | customerService.transferCustomer(reqVO, getLoginUserId()); |
| 130 | 135 | return success(true); |
| 131 | 136 | } |
| 132 | 137 | |
| 138 | + @GetMapping("/operate-log") | |
| 139 | + @Operation(summary = "获得客户操作日志") | |
| 140 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 141 | + @PreAuthorize("@ss.hasPermission('crm:customer:query')") | |
| 142 | + public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) { | |
| 143 | + // 1. 获取客户 | |
| 144 | + CrmCustomerDO customer = customerService.getCustomer(id); | |
| 145 | + if (customer == null) { | |
| 146 | + return success(null); | |
| 147 | + } | |
| 148 | + | |
| 149 | + // 2. 获取操作日志 | |
| 150 | + return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); | |
| 151 | + } | |
| 152 | + | |
| 133 | 153 | // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; |
| 134 | 154 | @PutMapping("/lock") |
| 135 | 155 | @Operation(summary = "锁定/解锁客户") | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java
| ... | ... | @@ -3,17 +3,20 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.validation.Mobile; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.validation.Telephone; |
| 6 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; |
| 8 | +import com.mzt.logapi.starter.annotation.DiffLogField; | |
| 7 | 9 | import io.swagger.v3.oas.annotations.media.Schema; |
| 8 | -import lombok.Data; | |
| 9 | -import org.springframework.format.annotation.DateTimeFormat; | |
| 10 | - | |
| 11 | 10 | import jakarta.validation.constraints.Email; |
| 12 | 11 | import jakarta.validation.constraints.NotEmpty; |
| 13 | 12 | import jakarta.validation.constraints.Size; |
| 13 | +import lombok.Data; | |
| 14 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 15 | + | |
| 14 | 16 | import java.time.LocalDateTime; |
| 15 | 17 | |
| 16 | 18 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 19 | +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; | |
| 17 | 20 | |
| 18 | 21 | /** |
| 19 | 22 | * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 |
| ... | ... | @@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 23 | 26 | public class CrmCustomerBaseVO { |
| 24 | 27 | |
| 25 | 28 | @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") |
| 29 | + @DiffLogField(name = "客户名称") | |
| 26 | 30 | @NotEmpty(message = "客户名称不能为空") |
| 27 | 31 | private String name; |
| 28 | 32 | |
| 29 | 33 | @Schema(description = "所属行业", example = "1") |
| 34 | + @DiffLogField(name = "所属行业", function = "getIndustryById") | |
| 35 | + @DictFormat(CRM_CUSTOMER_INDUSTRY) | |
| 30 | 36 | private Integer industryId; |
| 31 | 37 | |
| 32 | 38 | @Schema(description = "客户等级", example = "2") |
| 39 | + @DiffLogField(name = "客户等级", function = "getLevel") | |
| 33 | 40 | @InEnum(CrmCustomerLevelEnum.class) |
| 34 | 41 | private Integer level; |
| 35 | 42 | |
| 36 | 43 | @Schema(description = "客户来源", example = "3") |
| 44 | + @DiffLogField(name = "客户来源", function = "getSource") | |
| 37 | 45 | private Integer source; |
| 38 | 46 | |
| 39 | 47 | @Schema(description = "手机", example = "18000000000") |
| 48 | + @DiffLogField(name = "手机") | |
| 40 | 49 | @Mobile |
| 41 | 50 | private String mobile; |
| 42 | 51 | |
| 43 | 52 | @Schema(description = "电话", example = "18000000000") |
| 53 | + @DiffLogField(name = "电话") | |
| 44 | 54 | @Telephone |
| 45 | 55 | private String telephone; |
| 46 | 56 | |
| 47 | 57 | @Schema(description = "网址", example = "https://www.baidu.com") |
| 58 | + @DiffLogField(name = "网址") | |
| 48 | 59 | private String website; |
| 49 | 60 | |
| 50 | 61 | @Schema(description = "QQ", example = "123456789") |
| 62 | + @DiffLogField(name = "QQ") | |
| 51 | 63 | @Size(max = 20, message = "QQ长度不能超过 20 个字符") |
| 52 | 64 | private String qq; |
| 53 | 65 | |
| 54 | - @Schema(description = "wechat", example = "123456789") | |
| 66 | + @Schema(description = "微信", example = "123456789") | |
| 67 | + @DiffLogField(name = "微信") | |
| 55 | 68 | @Size(max = 255, message = "微信长度不能超过 255 个字符") |
| 56 | 69 | private String wechat; |
| 57 | 70 | |
| 58 | - @Schema(description = "email", example = "123456789@qq.com") | |
| 71 | + @Schema(description = "邮箱", example = "123456789@qq.com") | |
| 72 | + @DiffLogField(name = "邮箱") | |
| 59 | 73 | @Email(message = "邮箱格式不正确") |
| 60 | 74 | @Size(max = 255, message = "邮箱长度不能超过 255 个字符") |
| 61 | 75 | private String email; |
| 62 | 76 | |
| 63 | 77 | @Schema(description = "客户描述", example = "任意文字") |
| 78 | + @DiffLogField(name = "客户描述") | |
| 64 | 79 | @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") |
| 65 | 80 | private String description; |
| 66 | 81 | |
| 67 | 82 | @Schema(description = "备注", example = "随便") |
| 83 | + @DiffLogField(name = "备注") | |
| 68 | 84 | private String remark; |
| 69 | 85 | |
| 70 | 86 | @Schema(description = "地区编号", example = "20158") |
| 87 | + @DiffLogField(name = "地区编号", function = "getAreaById") | |
| 71 | 88 | private Integer areaId; |
| 72 | 89 | |
| 73 | 90 | @Schema(description = "详细地址", example = "北京市海淀区") |
| 91 | + @DiffLogField(name = "详细地址") | |
| 74 | 92 | private String detailAddress; |
| 75 | 93 | |
| 76 | 94 | @Schema(description = "下次联系时间") |
| 95 | + @DiffLogField(name = "下次联系时间") | |
| 77 | 96 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 78 | 97 | private LocalDateTime contactNextTime; |
| 79 | 98 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java
| ... | ... | @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 4 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import lombok.Data; | |
| 6 | - | |
| 7 | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | |
| 8 | 7 | |
| 9 | 8 | @Schema(description = "管理后台 - CRM 客户转移 Request VO") |
| 10 | 9 | @Data |
| 11 | 10 | public class CrmCustomerTransferReqVO { |
| 12 | 11 | |
| 13 | 12 | @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 14 | - @NotNull(message = "联系人编号不能为空") | |
| 13 | + @NotNull(message = "客户编号不能为空") | |
| 15 | 14 | private Long id; |
| 16 | 15 | |
| 17 | 16 | /** | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
| ... | ... | @@ -7,10 +7,7 @@ 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.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; | |
| 10 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.*; | |
| 14 | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; |
| 15 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| ... | ... | @@ -36,6 +33,7 @@ import java.util.Map; |
| 36 | 33 | import java.util.stream.Stream; |
| 37 | 34 | |
| 38 | 35 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 36 | +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | |
| 39 | 37 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; |
| 40 | 38 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 41 | 39 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| ... | ... | @@ -94,7 +92,7 @@ public class CrmReceivableController { |
| 94 | 92 | @Operation(summary = "获得回款分页") |
| 95 | 93 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") |
| 96 | 94 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { |
| 97 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO); | |
| 95 | + PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId()); | |
| 98 | 96 | return success(convertDetailReceivablePage(pageResult)); |
| 99 | 97 | } |
| 100 | 98 | |
| ... | ... | @@ -102,7 +100,7 @@ public class CrmReceivableController { |
| 102 | 100 | @Operation(summary = "获得回款分页,基于指定客户") |
| 103 | 101 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { |
| 104 | 102 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 105 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomer(pageReqVO); | |
| 103 | + PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); | |
| 106 | 104 | return success(convertDetailReceivablePage(pageResult)); |
| 107 | 105 | } |
| 108 | 106 | |
| ... | ... | @@ -113,7 +111,8 @@ public class CrmReceivableController { |
| 113 | 111 | @OperateLog(type = EXPORT) |
| 114 | 112 | public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, |
| 115 | 113 | HttpServletResponse response) throws IOException { |
| 116 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO); | |
| 114 | + exportReqVO.setPageSize(PAGE_SIZE_NONE); | |
| 115 | + PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId()); | |
| 117 | 116 | // 导出 Excel |
| 118 | 117 | ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, |
| 119 | 118 | convertDetailReceivablePage(pageResult).getList()); |
| ... | ... | @@ -142,4 +141,12 @@ public class CrmReceivableController { |
| 142 | 141 | return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); |
| 143 | 142 | } |
| 144 | 143 | |
| 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 | + | |
| 145 | 152 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java
| ... | ... | @@ -7,10 +7,7 @@ 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.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; | |
| 10 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.*; | |
| 14 | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; |
| 15 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| ... | ... | @@ -38,6 +35,7 @@ import java.util.Map; |
| 38 | 35 | import java.util.stream.Stream; |
| 39 | 36 | |
| 40 | 37 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 38 | +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | |
| 41 | 39 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; |
| 42 | 40 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 43 | 41 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| ... | ... | @@ -65,7 +63,7 @@ public class CrmReceivablePlanController { |
| 65 | 63 | @Operation(summary = "创建回款计划") |
| 66 | 64 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") |
| 67 | 65 | public CommonResult<Long> createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) { |
| 68 | - return success(receivablePlanService.createReceivablePlan(createReqVO)); | |
| 66 | + return success(receivablePlanService.createReceivablePlan(createReqVO, getLoginUserId())); | |
| 69 | 67 | } |
| 70 | 68 | |
| 71 | 69 | @PutMapping("/update") |
| ... | ... | @@ -98,7 +96,7 @@ public class CrmReceivablePlanController { |
| 98 | 96 | @Operation(summary = "获得回款计划分页") |
| 99 | 97 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 100 | 98 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 101 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO); | |
| 99 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); | |
| 102 | 100 | return success(convertDetailReceivablePlanPage(pageResult)); |
| 103 | 101 | } |
| 104 | 102 | |
| ... | ... | @@ -106,7 +104,7 @@ public class CrmReceivablePlanController { |
| 106 | 104 | @Operation(summary = "获得回款计划分页,基于指定客户") |
| 107 | 105 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 108 | 106 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 109 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomer(pageReqVO); | |
| 107 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); | |
| 110 | 108 | return success(convertDetailReceivablePlanPage(pageResult)); |
| 111 | 109 | } |
| 112 | 110 | |
| ... | ... | @@ -117,7 +115,8 @@ public class CrmReceivablePlanController { |
| 117 | 115 | @OperateLog(type = EXPORT) |
| 118 | 116 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, |
| 119 | 117 | HttpServletResponse response) throws IOException { |
| 120 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO); | |
| 118 | + exportReqVO.setPageSize(PAGE_SIZE_NONE); | |
| 119 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()); | |
| 121 | 120 | // 导出 Excel |
| 122 | 121 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, |
| 123 | 122 | convertDetailReceivablePlanPage(pageResult).getList()); |
| ... | ... | @@ -149,4 +148,12 @@ public class CrmReceivablePlanController { |
| 149 | 148 | return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); |
| 150 | 149 | } |
| 151 | 150 | |
| 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 | + | |
| 152 | 159 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java
| ... | ... | @@ -25,7 +25,4 @@ public class CrmReceivablePlanPageReqVO extends PageParam { |
| 25 | 25 | @InEnum(CrmSceneTypeEnum.class) |
| 26 | 26 | private Integer sceneType; // 场景类型,为 null 时则表示全部 |
| 27 | 27 | |
| 28 | - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | |
| 29 | - private Boolean pool; // null 则表示为不是公海数据 | |
| 30 | - | |
| 31 | 28 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - CRM 回款计划转移 Request VO") | |
| 9 | +@Data | |
| 10 | +public class CrmReceivablePlanTransferReqVO { | |
| 11 | + | |
| 12 | + @Schema(description = "回款计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 13 | + @NotNull(message = "回款计划编号不能为空") | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 新负责人的用户编号 | |
| 18 | + */ | |
| 19 | + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 20 | + @NotNull(message = "新负责人的用户编号不能为空") | |
| 21 | + private Long newOwnerUserId; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 老负责人加入团队后的权限级别。如果 null 说明移除 | |
| 25 | + * | |
| 26 | + * 关联 {@link CrmPermissionLevelEnum} | |
| 27 | + */ | |
| 28 | + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 29 | + private Integer oldOwnerPermissionLevel; | |
| 30 | + | |
| 31 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java
| ... | ... | @@ -27,7 +27,4 @@ public class CrmReceivablePageReqVO extends PageParam { |
| 27 | 27 | @InEnum(CrmSceneTypeEnum.class) |
| 28 | 28 | private Integer sceneType; // 场景类型,为 null 时则表示全部 |
| 29 | 29 | |
| 30 | - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | |
| 31 | - private Boolean pool; // null 则表示为不是公海数据 | |
| 32 | - | |
| 33 | 30 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - CRM 回款转移 Request VO") | |
| 9 | +@Data | |
| 10 | +public class CrmReceivableTransferReqVO { | |
| 11 | + | |
| 12 | + @Schema(description = "回款编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 13 | + @NotNull(message = "回款编号不能为空") | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 新负责人的用户编号 | |
| 18 | + */ | |
| 19 | + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | |
| 20 | + @NotNull(message = "新负责人的用户编号不能为空") | |
| 21 | + private Long newOwnerUserId; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 老负责人加入团队后的权限级别。如果 null 说明移除 | |
| 25 | + * | |
| 26 | + * 关联 {@link CrmPermissionLevelEnum} | |
| 27 | + */ | |
| 28 | + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 29 | + private Integer oldOwnerPermissionLevel; | |
| 30 | + | |
| 31 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.convert.clue; |
| 2 | 2 | |
| 3 | -import java.util.*; | |
| 4 | - | |
| 5 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | - | |
| 7 | -import org.mapstruct.Mapper; | |
| 8 | -import org.mapstruct.factory.Mappers; | |
| 9 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; |
| 10 | 5 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 6 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | |
| 7 | +import org.mapstruct.Mapper; | |
| 8 | +import org.mapstruct.Mapping; | |
| 9 | +import org.mapstruct.factory.Mappers; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 11 | 12 | |
| 12 | 13 | /** |
| 13 | 14 | * 线索 Convert |
| ... | ... | @@ -29,4 +30,7 @@ public interface CrmClueConvert { |
| 29 | 30 | |
| 30 | 31 | List<CrmClueExcelVO> convertList02(List<CrmClueDO> list); |
| 31 | 32 | |
| 33 | + @Mapping(target = "bizId", source = "reqVO.id") | |
| 34 | + CrmPermissionTransferReqBO convert(CrmClueTransferReqVO reqVO, Long userId); | |
| 35 | + | |
| 32 | 36 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
| ... | ... | @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe |
| 9 | 9 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 10 | 10 | import org.mapstruct.Mapper; |
| 11 | 11 | import org.mapstruct.Mapping; |
| 12 | -import org.mapstruct.Mappings; | |
| 13 | 12 | import org.mapstruct.factory.Mappers; |
| 14 | 13 | |
| 15 | 14 | import java.util.List; |
| ... | ... | @@ -26,9 +25,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd |
| 26 | 25 | * @author 芋道源码 |
| 27 | 26 | */ |
| 28 | 27 | @Mapper |
| 29 | -public interface ContactConvert { | |
| 28 | +public interface CrmContactConvert { | |
| 30 | 29 | |
| 31 | - ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class); | |
| 30 | + CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); | |
| 32 | 31 | |
| 33 | 32 | CrmContactDO convert(CrmContactCreateReqVO bean); |
| 34 | 33 | |
| ... | ... | @@ -48,10 +47,7 @@ public interface ContactConvert { |
| 48 | 47 | |
| 49 | 48 | List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list); |
| 50 | 49 | |
| 51 | - @Mappings({ | |
| 52 | - @Mapping(target = "bizId", source = "reqVO.id"), | |
| 53 | - @Mapping(target = "newOwnerUserId", source = "reqVO.id") | |
| 54 | - }) | |
| 50 | + @Mapping(target = "bizId", source = "reqVO.id") | |
| 55 | 51 | CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); |
| 56 | 52 | |
| 57 | 53 | /** | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java
| ... | ... | @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe |
| 8 | 8 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 9 | 9 | import org.mapstruct.Mapper; |
| 10 | 10 | import org.mapstruct.Mapping; |
| 11 | -import org.mapstruct.Mappings; | |
| 12 | 11 | import org.mapstruct.factory.Mappers; |
| 13 | 12 | |
| 14 | 13 | import java.util.List; |
| ... | ... | @@ -23,9 +22,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd |
| 23 | 22 | * @author dhb52 |
| 24 | 23 | */ |
| 25 | 24 | @Mapper |
| 26 | -public interface ContractConvert { | |
| 25 | +public interface CrmContractConvert { | |
| 27 | 26 | |
| 28 | - ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class); | |
| 27 | + CrmContractConvert INSTANCE = Mappers.getMapper(CrmContractConvert.class); | |
| 29 | 28 | |
| 30 | 29 | CrmContractDO convert(CrmContractCreateReqVO bean); |
| 31 | 30 | |
| ... | ... | @@ -39,10 +38,7 @@ public interface ContractConvert { |
| 39 | 38 | |
| 40 | 39 | List<CrmContractExcelVO> convertList02(List<CrmContractDO> list); |
| 41 | 40 | |
| 42 | - @Mappings({ | |
| 43 | - @Mapping(target = "bizId", source = "reqVO.id"), | |
| 44 | - @Mapping(target = "newOwnerUserId", source = "reqVO.id") | |
| 45 | - }) | |
| 41 | + @Mapping(target = "bizId", source = "reqVO.id") | |
| 46 | 42 | CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); |
| 47 | 43 | |
| 48 | 44 | default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap, | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java
| ... | ... | @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.crm.convert.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.CrmReceivableRespVO; |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 8 | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 11 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | |
| 10 | 12 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 11 | 13 | import org.mapstruct.Mapper; |
| 14 | +import org.mapstruct.Mapping; | |
| 12 | 15 | import org.mapstruct.factory.Mappers; |
| 13 | 16 | |
| 14 | 17 | import java.util.List; |
| ... | ... | @@ -58,4 +61,7 @@ public interface CrmReceivableConvert { |
| 58 | 61 | findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); |
| 59 | 62 | } |
| 60 | 63 | |
| 64 | + @Mapping(target = "bizId", source = "reqVO.id") | |
| 65 | + CrmPermissionTransferReqBO convert(CrmReceivableTransferReqVO reqVO, Long userId); | |
| 66 | + | |
| 61 | 67 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java
| ... | ... | @@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.crm.convert.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.CrmReceivablePlanRespVO; |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 8 | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 10 | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 12 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | |
| 11 | 13 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 12 | 14 | import org.mapstruct.Mapper; |
| 15 | +import org.mapstruct.Mapping; | |
| 13 | 16 | import org.mapstruct.factory.Mappers; |
| 14 | 17 | |
| 15 | 18 | import java.util.List; |
| ... | ... | @@ -63,4 +66,7 @@ public interface CrmReceivablePlanConvert { |
| 63 | 66 | findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); |
| 64 | 67 | } |
| 65 | 68 | |
| 69 | + @Mapping(target = "bizId", source = "reqVO.id") | |
| 70 | + CrmPermissionTransferReqBO convert(CrmReceivablePlanTransferReqVO reqVO, Long userId); | |
| 71 | + | |
| 66 | 72 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 5 | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; |
| ... | ... | @@ -27,14 +28,23 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { |
| 27 | 28 | .set(CrmBusinessDO::getOwnerUserId, ownerUserId)); |
| 28 | 29 | } |
| 29 | 30 | |
| 31 | + default PageResult<CrmBusinessDO> selectPageByCustomerId(CrmBusinessPageReqVO pageReqVO) { | |
| 32 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmBusinessDO>() | |
| 33 | + .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 | |
| 34 | + .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) | |
| 35 | + .orderByDesc(CrmBusinessDO::getId)); | |
| 36 | + } | |
| 37 | + | |
| 30 | 38 | default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { |
| 31 | 39 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); |
| 32 | 40 | // 拼接数据权限的查询条件 |
| 33 | - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, | |
| 34 | - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 41 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), | |
| 42 | + CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | |
| 43 | + if (!condition) { | |
| 44 | + return PageResult.empty(); | |
| 45 | + } | |
| 35 | 46 | // 拼接自身的查询条件 |
| 36 | 47 | query.selectAll(CrmBusinessDO.class) |
| 37 | - .eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 | |
| 38 | 48 | .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) |
| 39 | 49 | .orderByDesc(CrmBusinessDO::getId); |
| 40 | 50 | return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); |
| ... | ... | @@ -43,7 +53,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { |
| 43 | 53 | default List<CrmBusinessDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 44 | 54 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); |
| 45 | 55 | // 拼接数据权限的查询条件 |
| 46 | - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); | |
| 56 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); | |
| 47 | 57 | return selectJoinList(CrmBusinessDO.class, query); |
| 48 | 58 | } |
| 49 | 59 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
| ... | ... | @@ -30,8 +30,11 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { |
| 30 | 30 | default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { |
| 31 | 31 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); |
| 32 | 32 | // 拼接数据权限的查询条件 |
| 33 | - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, | |
| 34 | - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 33 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), | |
| 34 | + CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 35 | + if (!condition) { | |
| 36 | + return PageResult.empty(); | |
| 37 | + } | |
| 35 | 38 | // 拼接自身的查询条件 |
| 36 | 39 | query.selectAll(CrmClueDO.class) |
| 37 | 40 | .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) |
| ... | ... | @@ -44,7 +47,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { |
| 44 | 47 | default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 45 | 48 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); |
| 46 | 49 | // 拼接数据权限的查询条件 |
| 47 | - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); | |
| 50 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); | |
| 48 | 51 | return selectJoinList(CrmClueDO.class, query); |
| 49 | 52 | } |
| 50 | 53 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contact; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 5 | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| ... | ... | @@ -27,14 +28,28 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { |
| 27 | 28 | .set(CrmContactDO::getOwnerUserId, ownerUserId)); |
| 28 | 29 | } |
| 29 | 30 | |
| 31 | + default PageResult<CrmContactDO> selectPageByCustomerId(CrmContactPageReqVO pageVO) { | |
| 32 | + return selectPage(pageVO, new LambdaQueryWrapperX<CrmContactDO>() | |
| 33 | + .eq(CrmContactDO::getCustomerId, pageVO.getCustomerId()) // 指定客户编号 | |
| 34 | + .likeIfPresent(CrmContactDO::getName, pageVO.getName()) | |
| 35 | + .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile()) | |
| 36 | + .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone()) | |
| 37 | + .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail()) | |
| 38 | + .eqIfPresent(CrmContactDO::getQq, pageVO.getQq()) | |
| 39 | + .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat()) | |
| 40 | + .orderByDesc(CrmContactDO::getId)); | |
| 41 | + } | |
| 42 | + | |
| 30 | 43 | default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { |
| 31 | 44 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); |
| 32 | 45 | // 拼接数据权限的查询条件 |
| 33 | - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, | |
| 34 | - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 46 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), | |
| 47 | + CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | |
| 48 | + if (!condition) { | |
| 49 | + return PageResult.empty(); | |
| 50 | + } | |
| 35 | 51 | // 拼接自身的查询条件 |
| 36 | 52 | query.selectAll(CrmContactDO.class) |
| 37 | - .eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 | |
| 38 | 53 | .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) |
| 39 | 54 | .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) |
| 40 | 55 | .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) |
| ... | ... | @@ -48,7 +63,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { |
| 48 | 63 | default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 49 | 64 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); |
| 50 | 65 | // 拼接数据权限的查询条件 |
| 51 | - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); | |
| 66 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); | |
| 52 | 67 | return selectJoinList(CrmContactDO.class, query); |
| 53 | 68 | } |
| 54 | 69 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 5 | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| ... | ... | @@ -27,13 +28,26 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { |
| 27 | 28 | .set(CrmContractDO::getOwnerUserId, ownerUserId)); |
| 28 | 29 | } |
| 29 | 30 | |
| 31 | + default PageResult<CrmContractDO> selectPageByCustomerId(CrmContractPageReqVO pageReqVO) { | |
| 32 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmContractDO>() | |
| 33 | + .eq(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) | |
| 34 | + .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) | |
| 35 | + .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) | |
| 36 | + .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) | |
| 37 | + .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) | |
| 38 | + .orderByDesc(CrmContractDO::getId)); | |
| 39 | + } | |
| 40 | + | |
| 30 | 41 | default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { |
| 31 | 42 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); |
| 32 | - // 构建数据权限连表条件 | |
| 33 | - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, | |
| 34 | - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 43 | + // 拼接数据权限的查询条件 | |
| 44 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), | |
| 45 | + CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | |
| 46 | + if (!condition) { | |
| 47 | + return PageResult.empty(); | |
| 48 | + } | |
| 49 | + // 拼接自身的查询条件 | |
| 35 | 50 | mpjLambdaWrapperX.selectAll(CrmContractDO.class) |
| 36 | - .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) | |
| 37 | 51 | .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) |
| 38 | 52 | .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) |
| 39 | 53 | .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) |
| ... | ... | @@ -45,7 +59,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { |
| 45 | 59 | default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 46 | 60 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); |
| 47 | 61 | // 构建数据权限连表条件 |
| 48 | - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); | |
| 62 | + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); | |
| 49 | 63 | return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); |
| 50 | 64 | } |
| 51 | 65 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
| ... | ... | @@ -30,8 +30,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { |
| 30 | 30 | default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { |
| 31 | 31 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); |
| 32 | 32 | // 拼接数据权限的查询条件 |
| 33 | - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, | |
| 34 | - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 33 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | |
| 34 | + CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | |
| 35 | + if (!condition) { | |
| 36 | + return PageResult.empty(); | |
| 37 | + } | |
| 35 | 38 | // 拼接自身的查询条件 |
| 36 | 39 | query.selectAll(CrmCustomerDO.class) |
| 37 | 40 | .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) |
| ... | ... | @@ -45,7 +48,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { |
| 45 | 48 | default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 46 | 49 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); |
| 47 | 50 | // 拼接数据权限的查询条件 |
| 48 | - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); | |
| 51 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); | |
| 49 | 52 | return selectJoinList(CrmCustomerDO.class, query); |
| 50 | 53 | } |
| 51 | 54 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
| ... | ... | @@ -46,4 +46,10 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> { |
| 46 | 46 | .eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId)); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | + default int deletePermission(Integer bizType, Long bizId) { | |
| 50 | + return delete(new LambdaQueryWrapperX<CrmPermissionDO>() | |
| 51 | + .eq(CrmPermissionDO::getBizType, bizType) | |
| 52 | + .eq(CrmPermissionDO::getBizId, bizId)); | |
| 53 | + } | |
| 54 | + | |
| 49 | 55 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
| ... | ... | @@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 9 | +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | |
| 10 | +import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; | |
| 11 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 8 | 12 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 13 | |
| 14 | +import java.util.Collection; | |
| 15 | +import java.util.List; | |
| 16 | + | |
| 10 | 17 | /** |
| 11 | 18 | * 回款 Mapper |
| 12 | 19 | * |
| ... | ... | @@ -15,15 +22,13 @@ import org.apache.ibatis.annotations.Mapper; |
| 15 | 22 | @Mapper |
| 16 | 23 | public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { |
| 17 | 24 | |
| 18 | - default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO reqVO) { | |
| 19 | - return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() | |
| 20 | - .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) | |
| 21 | - .eqIfPresent(CrmReceivableDO::getPlanId, reqVO.getPlanId()) | |
| 22 | - .eqIfPresent(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) | |
| 23 | - .orderByDesc(CrmReceivableDO::getId)); | |
| 25 | + default int updateOwnerUserIdById(Long id, Long ownerUserId) { | |
| 26 | + return update(new LambdaUpdateWrapper<CrmReceivableDO>() | |
| 27 | + .eq(CrmReceivableDO::getId, id) | |
| 28 | + .set(CrmReceivableDO::getOwnerUserId, ownerUserId)); | |
| 24 | 29 | } |
| 25 | 30 | |
| 26 | - default PageResult<CrmReceivableDO> selectPageByCustomer(CrmReceivablePageReqVO reqVO) { | |
| 31 | + default PageResult<CrmReceivableDO> selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { | |
| 27 | 32 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() |
| 28 | 33 | .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 |
| 29 | 34 | .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) |
| ... | ... | @@ -31,4 +36,27 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { |
| 31 | 36 | .orderByDesc(CrmReceivableDO::getId)); |
| 32 | 37 | } |
| 33 | 38 | |
| 39 | + default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { | |
| 40 | + MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); | |
| 41 | + // 拼接数据权限的查询条件 | |
| 42 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), | |
| 43 | + CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | |
| 44 | + if (!condition) { | |
| 45 | + return PageResult.empty(); | |
| 46 | + } | |
| 47 | + // 拼接自身的查询条件 | |
| 48 | + query.selectAll(CrmReceivableDO.class) | |
| 49 | + .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) | |
| 50 | + .eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId()) | |
| 51 | + .orderByDesc(CrmReceivableDO::getId); | |
| 52 | + return selectJoinPage(pageReqVO, CrmReceivableDO.class, query); | |
| 53 | + } | |
| 54 | + | |
| 55 | + default List<CrmReceivableDO> selectBatchIds(Collection<Long> ids, Long userId) { | |
| 56 | + MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); | |
| 57 | + // 拼接数据权限的查询条件 | |
| 58 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); | |
| 59 | + return selectJoinList(CrmReceivableDO.class, query); | |
| 60 | + } | |
| 61 | + | |
| 34 | 62 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
| ... | ... | @@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 9 | +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | |
| 10 | +import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; | |
| 11 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 8 | 12 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 13 | |
| 14 | +import java.util.Collection; | |
| 15 | +import java.util.List; | |
| 16 | + | |
| 10 | 17 | /** |
| 11 | 18 | * 回款计划 Mapper |
| 12 | 19 | * |
| ... | ... | @@ -15,18 +22,40 @@ import org.apache.ibatis.annotations.Mapper; |
| 15 | 22 | @Mapper |
| 16 | 23 | public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> { |
| 17 | 24 | |
| 18 | - default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO reqVO) { | |
| 19 | - return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>() | |
| 20 | - .eqIfPresent(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) | |
| 21 | - .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) | |
| 22 | - .orderByDesc(CrmReceivablePlanDO::getId)); | |
| 25 | + default int updateOwnerUserIdById(Long id, Long ownerUserId) { | |
| 26 | + return update(new LambdaUpdateWrapper<CrmReceivablePlanDO>() | |
| 27 | + .eq(CrmReceivablePlanDO::getId, id) | |
| 28 | + .set(CrmReceivablePlanDO::getOwnerUserId, ownerUserId)); | |
| 23 | 29 | } |
| 24 | 30 | |
| 25 | - default PageResult<CrmReceivablePlanDO> selectPageByCustomer(CrmReceivablePlanPageReqVO reqVO) { | |
| 31 | + default PageResult<CrmReceivablePlanDO> selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) { | |
| 26 | 32 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>() |
| 27 | 33 | .eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 |
| 28 | 34 | .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) |
| 29 | 35 | .orderByDesc(CrmReceivablePlanDO::getId)); |
| 30 | 36 | } |
| 31 | 37 | |
| 38 | + default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { | |
| 39 | + MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); | |
| 40 | + // 拼接数据权限的查询条件 | |
| 41 | + boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), | |
| 42 | + CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | |
| 43 | + if (!condition) { | |
| 44 | + return PageResult.empty(); | |
| 45 | + } | |
| 46 | + // 拼接自身的查询条件 | |
| 47 | + query.selectAll(CrmReceivablePlanDO.class) | |
| 48 | + .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) | |
| 49 | + .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) | |
| 50 | + .orderByDesc(CrmReceivablePlanDO::getId); | |
| 51 | + return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); | |
| 52 | + } | |
| 53 | + | |
| 54 | + default List<CrmReceivablePlanDO> selectBatchIds(Collection<Long> ids, Long userId) { | |
| 55 | + MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); | |
| 56 | + // 拼接数据权限的查询条件 | |
| 57 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); | |
| 58 | + return selectJoinList(CrmReceivablePlanDO.class, query); | |
| 59 | + } | |
| 60 | + | |
| 32 | 61 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.bizlog.function; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | |
| 5 | +import com.mzt.logapi.service.IParseFunction; | |
| 6 | +import lombok.extern.slf4j.Slf4j; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 自定义函数-通过行业编号获取行业信息 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Slf4j | |
| 17 | +@Component | |
| 18 | +public class CrmIndustryParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + @Override | |
| 21 | + public boolean executeBefore() { | |
| 22 | + return true; // 先转换值后对比 | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public String functionName() { | |
| 27 | + return "getIndustryById"; | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String apply(Object value) { | |
| 32 | + if (value == null) { | |
| 33 | + return ""; | |
| 34 | + } | |
| 35 | + if (StrUtil.isEmpty(value.toString())) { | |
| 36 | + return ""; | |
| 37 | + } | |
| 38 | + | |
| 39 | + // 获取行业信息 | |
| 40 | + try { | |
| 41 | + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); | |
| 42 | + } catch (Exception ignored) { | |
| 43 | + } | |
| 44 | + return ""; | |
| 45 | + } | |
| 46 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.bizlog.function; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | |
| 5 | +import com.mzt.logapi.service.IParseFunction; | |
| 6 | +import lombok.extern.slf4j.Slf4j; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 自定义函数-通过客户等级编号获取客户等级信息 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Slf4j | |
| 17 | +@Component | |
| 18 | +public class CrmLevelParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + @Override | |
| 21 | + public boolean executeBefore() { | |
| 22 | + return true; // 先转换值后对比 | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public String functionName() { | |
| 27 | + return "getLevel"; | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String apply(Object value) { | |
| 32 | + if (value == null) { | |
| 33 | + return ""; | |
| 34 | + } | |
| 35 | + if (StrUtil.isEmpty(value.toString())) { | |
| 36 | + return ""; | |
| 37 | + } | |
| 38 | + | |
| 39 | + // 获取客户等级信息 | |
| 40 | + try { | |
| 41 | + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString()); | |
| 42 | + } catch (Exception ignored) { | |
| 43 | + } | |
| 44 | + return ""; | |
| 45 | + } | |
| 46 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.bizlog.function; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | |
| 5 | +import com.mzt.logapi.service.IParseFunction; | |
| 6 | +import lombok.extern.slf4j.Slf4j; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 自定义函数-通过客户来源编号获取客户来源信息 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Slf4j | |
| 17 | +@Component | |
| 18 | +public class CrmSourceParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + @Override | |
| 21 | + public boolean executeBefore() { | |
| 22 | + return true; // 先转换值后对比 | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public String functionName() { | |
| 27 | + return "getSource"; | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String apply(Object value) { | |
| 32 | + if (value == null) { | |
| 33 | + return ""; | |
| 34 | + } | |
| 35 | + if (StrUtil.isEmpty(value.toString())) { | |
| 36 | + return ""; | |
| 37 | + } | |
| 38 | + | |
| 39 | + // 获取客户来源信息 | |
| 40 | + try { | |
| 41 | + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString()); | |
| 42 | + } catch (Exception ignored) { | |
| 43 | + } | |
| 44 | + return ""; | |
| 45 | + } | |
| 46 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java
0 → 100644
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
| ... | ... | @@ -75,10 +75,9 @@ public interface CrmBusinessService { |
| 75 | 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 |
| 76 | 76 | * |
| 77 | 77 | * @param pageReqVO 分页查询 |
| 78 | - * @param userId 用户编号 | |
| 79 | 78 | * @return 联系人分页 |
| 80 | 79 | */ |
| 81 | - PageResult<CrmBusinessDO> getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId); | |
| 80 | + PageResult<CrmBusinessDO> getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO); | |
| 82 | 81 | |
| 83 | 82 | /** |
| 84 | 83 | * 商机转移 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
| ... | ... | @@ -111,11 +111,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | @Override |
| 114 | - public PageResult<CrmBusinessDO> getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId) { | |
| 115 | - // 校验客户存在 TODO @puhui999:这里不校验 | |
| 116 | - customerService.validateCustomer(pageReqVO.getCustomerId()); | |
| 117 | - // TODO @puhui999:感觉这里貌似不太复用用 selectPage,因为他可能没商机权限,只是因为能看 customer,所以可以看到列表 | |
| 118 | - return businessMapper.selectPage(pageReqVO, userId); | |
| 114 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) | |
| 115 | + public PageResult<CrmBusinessDO> getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO) { | |
| 116 | + return businessMapper.selectPageByCustomerId(pageReqVO); | |
| 119 | 117 | } |
| 120 | 118 | |
| 121 | 119 | @Override |
| ... | ... | @@ -127,7 +125,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 127 | 125 | // 2.1 数据权限转移 |
| 128 | 126 | crmPermissionService.transferPermission( |
| 129 | 127 | CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); |
| 130 | - | |
| 131 | 128 | // 2.2 设置新的负责人 |
| 132 | 129 | businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 133 | 130 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.clue; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 8 | 9 | import jakarta.validation.Valid; |
| ... | ... | @@ -64,4 +65,12 @@ public interface CrmClueService { |
| 64 | 65 | */ |
| 65 | 66 | PageResult<CrmClueDO> getCluePage(CrmCluePageReqVO pageReqVO, Long userId); |
| 66 | 67 | |
| 68 | + /** | |
| 69 | + * 线索转移 | |
| 70 | + * | |
| 71 | + * @param reqVO 请求 | |
| 72 | + * @param userId 用户编号 | |
| 73 | + */ | |
| 74 | + void transferClue(CrmClueTransferReqVO reqVO, Long userId); | |
| 75 | + | |
| 67 | 76 | } | ... | ... |
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; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; |
| 8 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; | |
| 8 | 9 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; |
| 9 | 10 | import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; |
| 10 | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| ... | ... | @@ -101,4 +102,18 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 101 | 102 | return clueMapper.selectPage(pageReqVO, userId); |
| 102 | 103 | } |
| 103 | 104 | |
| 105 | + @Override | |
| 106 | + public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { | |
| 107 | + // 1 校验线索是否存在 | |
| 108 | + validateClueExists(reqVO.getId()); | |
| 109 | + | |
| 110 | + // 2.1 数据权限转移 | |
| 111 | + crmPermissionService.transferPermission( | |
| 112 | + CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); | |
| 113 | + // 2.2 设置新的负责人 | |
| 114 | + clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | |
| 115 | + | |
| 116 | + // 3. TODO 记录转移日志 | |
| 117 | + } | |
| 118 | + | |
| 104 | 119 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
| ... | ... | @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.service.contact; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 9 | +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | |
| 8 | 10 | import jakarta.validation.Valid; |
| 9 | 11 | |
| 10 | 12 | import java.util.Collection; |
| ... | ... | @@ -71,12 +73,19 @@ public interface CrmContactService { |
| 71 | 73 | /** |
| 72 | 74 | * 获得联系人分页 |
| 73 | 75 | * |
| 74 | - * 数据权限:基于 {@link CrmContactDO} | |
| 76 | + * 数据权限:基于 {@link CrmCustomerDO} | |
| 75 | 77 | * |
| 76 | 78 | * @param pageVO 分页查询 |
| 77 | - * @param userId 用户编号 | |
| 78 | 79 | * @return 联系人分页 |
| 79 | 80 | */ |
| 80 | - PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId); | |
| 81 | + PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO); | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * 联系人转移 | |
| 85 | + * | |
| 86 | + * @param reqVO 请求 | |
| 87 | + * @param userId 用户编号 | |
| 88 | + */ | |
| 89 | + void transferContact(CrmContactTransferReqVO reqVO, Long userId); | |
| 81 | 90 | |
| 82 | 91 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
| ... | ... | @@ -3,11 +3,8 @@ package cn.iocoder.yudao.module.crm.service.contact; |
| 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.module.crm.controller.admin.contact.vo.CrmContactBaseVO; | |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; | |
| 8 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; | |
| 9 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; | |
| 10 | -import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; | |
| 7 | +import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; | |
| 11 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 12 | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; |
| 13 | 10 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| ... | ... | @@ -56,7 +53,7 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 56 | 53 | // 1.1 校验 |
| 57 | 54 | validateRelationDataExists(createReqVO); |
| 58 | 55 | // 1.2 插入 |
| 59 | - CrmContactDO contact = ContactConvert.INSTANCE.convert(createReqVO); | |
| 56 | + CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); | |
| 60 | 57 | contactMapper.insert(contact); |
| 61 | 58 | |
| 62 | 59 | // 2. 创建数据权限 |
| ... | ... | @@ -73,7 +70,7 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 73 | 70 | validateContactExists(updateReqVO.getId()); |
| 74 | 71 | validateRelationDataExists(updateReqVO); |
| 75 | 72 | // 2. 更新 |
| 76 | - CrmContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO); | |
| 73 | + CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); | |
| 77 | 74 | contactMapper.updateById(updateObj); |
| 78 | 75 | } |
| 79 | 76 | |
| ... | ... | @@ -134,11 +131,23 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 134 | 131 | } |
| 135 | 132 | |
| 136 | 133 | @Override |
| 137 | - public PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId) { | |
| 138 | - // 校验用户存在 | |
| 139 | - customerService.validateCustomer(pageVO.getCustomerId()); | |
| 140 | - // TODO @puhui999:getBusinessPageByCustomer 同理 | |
| 141 | - return contactMapper.selectPage(pageVO, userId); | |
| 134 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageVO.customerId", level = CrmPermissionLevelEnum.READ) | |
| 135 | + public PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO) { | |
| 136 | + return contactMapper.selectPageByCustomerId(pageVO); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Override | |
| 140 | + public void transferContact(CrmContactTransferReqVO reqVO, Long userId) { | |
| 141 | + // 1 校验联系人是否存在 | |
| 142 | + validateContactExists(reqVO.getId()); | |
| 143 | + | |
| 144 | + // 2.1 数据权限转移 | |
| 145 | + crmPermissionService.transferPermission( | |
| 146 | + CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType())); | |
| 147 | + // 2.2 设置新的负责人 | |
| 148 | + contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | |
| 149 | + | |
| 150 | + // 3. TODO 记录转移日志 | |
| 142 | 151 | } |
| 143 | 152 | |
| 144 | 153 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
| ... | ... | @@ -75,12 +75,9 @@ public interface CrmContractService { |
| 75 | 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 |
| 76 | 76 | * |
| 77 | 77 | * @param pageReqVO 分页查询 |
| 78 | - * @param userId 用户编号 | |
| 79 | 78 | * @return 联系人分页 |
| 80 | 79 | */ |
| 81 | - default PageResult<CrmContractDO> getContractPageByCustomer(CrmContractPageReqVO pageReqVO, Long userId) { | |
| 82 | - return getContractPage(pageReqVO, userId); | |
| 83 | - } | |
| 80 | + PageResult<CrmContractDO> getContractPageByCustomerId(CrmContractPageReqVO pageReqVO); | |
| 84 | 81 | |
| 85 | 82 | /** |
| 86 | 83 | * 合同转移 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
| ... | ... | @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreat |
| 7 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; |
| 9 | 9 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; |
| 10 | -import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; | |
| 10 | +import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; | |
| 11 | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 12 | 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; |
| 13 | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| ... | ... | @@ -44,7 +44,7 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 44 | 44 | @Override |
| 45 | 45 | public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) { |
| 46 | 46 | // 插入 |
| 47 | - CrmContractDO contract = ContractConvert.INSTANCE.convert(createReqVO); | |
| 47 | + CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO); | |
| 48 | 48 | contractMapper.insert(contract); |
| 49 | 49 | |
| 50 | 50 | // 创建数据权限 |
| ... | ... | @@ -61,7 +61,7 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 61 | 61 | // 校验存在 |
| 62 | 62 | validateContractExists(updateReqVO.getId()); |
| 63 | 63 | // 更新 |
| 64 | - CrmContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO); | |
| 64 | + CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO); | |
| 65 | 65 | contractMapper.updateById(updateObj); |
| 66 | 66 | } |
| 67 | 67 | |
| ... | ... | @@ -105,6 +105,12 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | @Override |
| 108 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) | |
| 109 | + public PageResult<CrmContractDO> getContractPageByCustomerId(CrmContractPageReqVO pageReqVO) { | |
| 110 | + return contractMapper.selectPageByCustomerId(pageReqVO); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @Override | |
| 108 | 114 | @Transactional(rollbackFor = Exception.class) |
| 109 | 115 | public void transferContract(CrmContractTransferReqVO reqVO, Long userId) { |
| 110 | 116 | // 1. 校验合同是否存在 |
| ... | ... | @@ -112,7 +118,7 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 112 | 118 | |
| 113 | 119 | // 2.1 数据权限转移 |
| 114 | 120 | crmPermissionService.transferPermission( |
| 115 | - ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); | |
| 121 | + CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); | |
| 116 | 122 | // 2.2 设置负责人 |
| 117 | 123 | contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 118 | 124 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 5 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; |
| ... | ... | @@ -15,6 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; |
| 15 | 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 16 | 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 17 | 18 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 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; |
| ... | ... | @@ -24,6 +28,8 @@ import java.util.*; |
| 24 | 28 | |
| 25 | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | 30 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 31 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | |
| 32 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; | |
| 27 | 33 | import static java.util.Collections.singletonList; |
| 28 | 34 | |
| 29 | 35 | /** |
| ... | ... | @@ -59,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 59 | 65 | |
| 60 | 66 | @Override |
| 61 | 67 | @Transactional(rollbackFor = Exception.class) |
| 68 | + @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") | |
| 62 | 69 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 63 | 70 | public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { |
| 64 | 71 | // 校验存在 |
| 65 | - validateCustomerExists(updateReqVO.getId()); | |
| 72 | + CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); | |
| 66 | 73 | |
| 74 | + // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null | |
| 75 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); | |
| 67 | 76 | // 更新 |
| 68 | 77 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); |
| 69 | 78 | customerMapper.updateById(updateObj); |
| ... | ... | @@ -82,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 82 | 91 | crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); |
| 83 | 92 | } |
| 84 | 93 | |
| 85 | - private void validateCustomerExists(Long id) { | |
| 86 | - if (customerMapper.selectById(id) == null) { | |
| 94 | + private CrmCustomerDO validateCustomerExists(Long id) { | |
| 95 | + CrmCustomerDO customerDO = customerMapper.selectById(id); | |
| 96 | + if (customerDO == null) { | |
| 87 | 97 | throw exception(CUSTOMER_NOT_EXISTS); |
| 88 | 98 | } |
| 99 | + return customerDO; | |
| 89 | 100 | } |
| 90 | 101 | |
| 91 | 102 | @Override |
| ... | ... | @@ -114,7 +125,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 114 | 125 | */ |
| 115 | 126 | @Override |
| 116 | 127 | public void validateCustomer(Long customerId) { |
| 117 | - // TODO puhui999: 不返回客户不走校验应该可行 | |
| 118 | 128 | // 校验客户是否存在 |
| 119 | 129 | if (customerId == null) { |
| 120 | 130 | throw exception(CUSTOMER_NOT_EXISTS); |
| ... | ... | @@ -127,11 +137,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 127 | 137 | |
| 128 | 138 | @Override |
| 129 | 139 | @Transactional(rollbackFor = Exception.class) |
| 140 | + @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") | |
| 130 | 141 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) |
| 131 | 142 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { |
| 132 | 143 | // 1. 校验客户是否存在 |
| 133 | 144 | validateCustomer(reqVO.getId()); |
| 134 | - | |
| 145 | + // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 | |
| 146 | + LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); | |
| 135 | 147 | // 2.1 数据权限转移 |
| 136 | 148 | crmPermissionService.transferPermission( |
| 137 | 149 | CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
| ... | ... | @@ -138,15 +138,13 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | @Override |
| 141 | + @Transactional(rollbackFor = Exception.class) | |
| 141 | 142 | public void deletePermission(Integer bizType, Long bizId) { |
| 142 | - // TODO @puhui999:这种直接写条件删除;不需要先查询,再删除 | |
| 143 | - List<CrmPermissionDO> permissionList = crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId); | |
| 144 | - if (CollUtil.isEmpty(permissionList)) { | |
| 145 | - return; | |
| 146 | - } | |
| 147 | - | |
| 148 | 143 | // 删除数据权限 |
| 149 | - crmPermissionMapper.deleteBatchIds(convertSet(permissionList, CrmPermissionDO::getId)); | |
| 144 | + int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId); | |
| 145 | + if (deletedCol == 0) { | |
| 146 | + throw exception(CRM_PERMISSION_NOT_EXISTS); | |
| 147 | + } | |
| 150 | 148 | } |
| 151 | 149 | |
| 152 | 150 | @Override | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
| ... | ... | @@ -3,11 +3,12 @@ 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; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 8 | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 9 | - | |
| 10 | 10 | import jakarta.validation.Valid; |
| 11 | + | |
| 11 | 12 | import java.util.Collection; |
| 12 | 13 | import java.util.List; |
| 13 | 14 | |
| ... | ... | @@ -24,7 +25,7 @@ public interface CrmReceivablePlanService { |
| 24 | 25 | * @param createReqVO 创建信息 |
| 25 | 26 | * @return 编号 |
| 26 | 27 | */ |
| 27 | - Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO); | |
| 28 | + Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO, Long userId); | |
| 28 | 29 | |
| 29 | 30 | /** |
| 30 | 31 | * 更新回款计划 |
| ... | ... | @@ -62,9 +63,10 @@ public interface CrmReceivablePlanService { |
| 62 | 63 | * 数据权限:基于 {@link CrmReceivablePlanDO} 读取 |
| 63 | 64 | * |
| 64 | 65 | * @param pageReqVO 分页查询 |
| 66 | + * @param userId 用户编号 | |
| 65 | 67 | * @return 回款计划分页 |
| 66 | 68 | */ |
| 67 | - PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO); | |
| 69 | + PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId); | |
| 68 | 70 | |
| 69 | 71 | /** |
| 70 | 72 | * 获得回款计划分页,基于指定客户 |
| ... | ... | @@ -74,6 +76,14 @@ public interface CrmReceivablePlanService { |
| 74 | 76 | * @param pageReqVO 分页查询 |
| 75 | 77 | * @return 回款计划分页 |
| 76 | 78 | */ |
| 77 | - PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO); | |
| 79 | + PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO); | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * 回款计划转移 | |
| 83 | + * | |
| 84 | + * @param reqVO 请求 | |
| 85 | + * @param userId 用户编号 | |
| 86 | + */ | |
| 87 | + void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId); | |
| 78 | 88 | |
| 79 | 89 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
| ... | ... | @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; |
| 8 | 8 | 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; | |
| 9 | 10 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 10 | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; |
| 11 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| ... | ... | @@ -17,10 +18,12 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 17 | 18 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; |
| 18 | 19 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 19 | 20 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 21 | +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | |
| 22 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | |
| 23 | +import jakarta.annotation.Resource; | |
| 20 | 24 | import org.springframework.stereotype.Service; |
| 21 | 25 | import org.springframework.validation.annotation.Validated; |
| 22 | 26 | |
| 23 | -import jakarta.annotation.Resource; | |
| 24 | 27 | import java.util.Collection; |
| 25 | 28 | import java.util.List; |
| 26 | 29 | |
| ... | ... | @@ -28,7 +31,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU |
| 28 | 31 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 29 | 32 | |
| 30 | 33 | // TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈; |
| 31 | -// TODO @puhui999:数据权限 | |
| 34 | + | |
| 32 | 35 | /** |
| 33 | 36 | * 回款计划 Service 实现类 |
| 34 | 37 | * |
| ... | ... | @@ -45,9 +48,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { |
| 45 | 48 | private CrmContractService contractService; |
| 46 | 49 | @Resource |
| 47 | 50 | private CrmCustomerService customerService; |
| 51 | + @Resource | |
| 52 | + private CrmPermissionService crmPermissionService; | |
| 48 | 53 | |
| 49 | 54 | @Override |
| 50 | - public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO) { | |
| 55 | + public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) { | |
| 51 | 56 | // 插入 |
| 52 | 57 | CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); |
| 53 | 58 | receivablePlan.setFinishStatus(false); |
| ... | ... | @@ -55,29 +60,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { |
| 55 | 60 | checkReceivablePlan(receivablePlan); |
| 56 | 61 | |
| 57 | 62 | receivablePlanMapper.insert(receivablePlan); |
| 63 | + // 创建数据权限 | |
| 64 | + crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()) | |
| 65 | + .setBizId(receivablePlan.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); | |
| 58 | 66 | // 返回 |
| 59 | 67 | return receivablePlan.getId(); |
| 60 | 68 | } |
| 61 | 69 | |
| 62 | 70 | private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) { |
| 63 | 71 | |
| 64 | - if(ObjectUtil.isNull(receivablePlan.getContractId())){ | |
| 72 | + if (ObjectUtil.isNull(receivablePlan.getContractId())) { | |
| 65 | 73 | throw exception(CONTRACT_NOT_EXISTS); |
| 66 | 74 | } |
| 67 | 75 | |
| 68 | 76 | CrmContractDO contract = contractService.getContract(receivablePlan.getContractId()); |
| 69 | - if(ObjectUtil.isNull(contract)){ | |
| 77 | + if (ObjectUtil.isNull(contract)) { | |
| 70 | 78 | throw exception(CONTRACT_NOT_EXISTS); |
| 71 | 79 | } |
| 72 | 80 | |
| 73 | 81 | CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId()); |
| 74 | - if(ObjectUtil.isNull(customer)){ | |
| 82 | + if (ObjectUtil.isNull(customer)) { | |
| 75 | 83 | throw exception(CUSTOMER_NOT_EXISTS); |
| 76 | 84 | } |
| 77 | 85 | |
| 78 | 86 | } |
| 79 | 87 | |
| 80 | 88 | @Override |
| 89 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | |
| 81 | 90 | public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { |
| 82 | 91 | // 校验存在 |
| 83 | 92 | validateReceivablePlanExists(updateReqVO.getId()); |
| ... | ... | @@ -88,6 +97,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { |
| 88 | 97 | } |
| 89 | 98 | |
| 90 | 99 | @Override |
| 100 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | |
| 91 | 101 | public void deleteReceivablePlan(Long id) { |
| 92 | 102 | // 校验存在 |
| 93 | 103 | validateReceivablePlanExists(id); |
| ... | ... | @@ -102,6 +112,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { |
| 102 | 112 | } |
| 103 | 113 | |
| 104 | 114 | @Override |
| 115 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.READ) | |
| 105 | 116 | public CrmReceivablePlanDO getReceivablePlan(Long id) { |
| 106 | 117 | return receivablePlanMapper.selectById(id); |
| 107 | 118 | } |
| ... | ... | @@ -115,14 +126,28 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { |
| 115 | 126 | } |
| 116 | 127 | |
| 117 | 128 | @Override |
| 118 | - public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO) { | |
| 119 | - return receivablePlanMapper.selectPage(pageReqVO); | |
| 129 | + public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { | |
| 130 | + return receivablePlanMapper.selectPage(pageReqVO, userId); | |
| 120 | 131 | } |
| 121 | 132 | |
| 122 | 133 | @Override |
| 123 | 134 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) |
| 124 | - public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO) { | |
| 125 | - return receivablePlanMapper.selectPageByCustomer(pageReqVO); | |
| 135 | + public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO) { | |
| 136 | + return receivablePlanMapper.selectPageByCustomerId(pageReqVO); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Override | |
| 140 | + public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) { | |
| 141 | + // 1 校验回款计划是否存在 | |
| 142 | + validateReceivablePlanExists(reqVO.getId()); | |
| 143 | + | |
| 144 | + // 2.1 数据权限转移 | |
| 145 | + crmPermissionService.transferPermission( | |
| 146 | + CrmReceivablePlanConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType())); | |
| 147 | + // 2.2 设置新的负责人 | |
| 148 | + receivablePlanMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | |
| 149 | + | |
| 150 | + // 3. TODO 记录转移日志 | |
| 126 | 151 | } |
| 127 | 152 | |
| 128 | 153 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
| ... | ... | @@ -3,11 +3,12 @@ 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; | |
| 6 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 8 | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 9 | - | |
| 10 | 10 | import jakarta.validation.Valid; |
| 11 | + | |
| 11 | 12 | import java.util.Collection; |
| 12 | 13 | import java.util.List; |
| 13 | 14 | |
| ... | ... | @@ -62,9 +63,10 @@ public interface CrmReceivableService { |
| 62 | 63 | * 数据权限:基于 {@link CrmReceivableDO} 读取 |
| 63 | 64 | * |
| 64 | 65 | * @param pageReqVO 分页查询 |
| 66 | + * @param userId 用户编号 | |
| 65 | 67 | * @return 回款分页 |
| 66 | 68 | */ |
| 67 | - PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO); | |
| 69 | + PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId); | |
| 68 | 70 | |
| 69 | 71 | /** |
| 70 | 72 | * 获得回款分页,基于指定客户 |
| ... | ... | @@ -74,6 +76,14 @@ public interface CrmReceivableService { |
| 74 | 76 | * @param pageReqVO 分页查询 |
| 75 | 77 | * @return 回款分页 |
| 76 | 78 | */ |
| 77 | - PageResult<CrmReceivableDO> getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO); | |
| 79 | + PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO); | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * 回款转移 | |
| 83 | + * | |
| 84 | + * @param reqVO 请求 | |
| 85 | + * @param userId 用户编号 | |
| 86 | + */ | |
| 87 | + void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId); | |
| 78 | 88 | |
| 79 | 89 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | 8 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; |
| 9 | 9 | 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; | |
| 10 | 11 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 11 | 12 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; |
| 12 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| ... | ... | @@ -20,10 +21,11 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 20 | 21 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; |
| 21 | 22 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 22 | 23 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 24 | +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | |
| 25 | +import jakarta.annotation.Resource; | |
| 23 | 26 | import org.springframework.stereotype.Service; |
| 24 | 27 | import org.springframework.validation.annotation.Validated; |
| 25 | 28 | |
| 26 | -import jakarta.annotation.Resource; | |
| 27 | 29 | import java.util.Collection; |
| 28 | 30 | import java.util.List; |
| 29 | 31 | |
| ... | ... | @@ -48,6 +50,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { |
| 48 | 50 | private CrmCustomerService customerService; |
| 49 | 51 | @Resource |
| 50 | 52 | private CrmReceivablePlanService receivablePlanService; |
| 53 | + @Resource | |
| 54 | + private CrmPermissionService crmPermissionService; | |
| 51 | 55 | |
| 52 | 56 | // TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan? |
| 53 | 57 | @Override |
| ... | ... | @@ -70,22 +74,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { |
| 70 | 74 | // TODO @liuhongfeng:这里的括号要注意排版; |
| 71 | 75 | private void checkReceivable(CrmReceivableDO receivable) { |
| 72 | 76 | // TODO @liuhongfeng:这个放在参数校验合适 |
| 73 | - if(ObjectUtil.isNull(receivable.getContractId())){ | |
| 77 | + if (ObjectUtil.isNull(receivable.getContractId())) { | |
| 74 | 78 | throw exception(CONTRACT_NOT_EXISTS); |
| 75 | 79 | } |
| 76 | 80 | |
| 77 | 81 | CrmContractDO contract = contractService.getContract(receivable.getContractId()); |
| 78 | - if(ObjectUtil.isNull(contract)){ | |
| 82 | + if (ObjectUtil.isNull(contract)) { | |
| 79 | 83 | throw exception(CONTRACT_NOT_EXISTS); |
| 80 | 84 | } |
| 81 | 85 | |
| 82 | 86 | CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId()); |
| 83 | - if(ObjectUtil.isNull(customer)){ | |
| 87 | + if (ObjectUtil.isNull(customer)) { | |
| 84 | 88 | throw exception(CUSTOMER_NOT_EXISTS); |
| 85 | 89 | } |
| 86 | 90 | |
| 87 | 91 | CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId()); |
| 88 | - if(ObjectUtil.isNull(receivablePlan)){ | |
| 92 | + if (ObjectUtil.isNull(receivablePlan)) { | |
| 89 | 93 | throw exception(RECEIVABLE_PLAN_NOT_EXISTS); |
| 90 | 94 | } |
| 91 | 95 | |
| ... | ... | @@ -129,16 +133,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { |
| 129 | 133 | return receivableMapper.selectBatchIds(ids); |
| 130 | 134 | } |
| 131 | 135 | |
| 132 | - // TODO @芋艿:数据权限 | |
| 133 | 136 | @Override |
| 134 | - public PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO) { | |
| 135 | - return receivableMapper.selectPage(pageReqVO); | |
| 137 | + public PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId) { | |
| 138 | + return receivableMapper.selectPage(pageReqVO, userId); | |
| 136 | 139 | } |
| 137 | 140 | |
| 138 | 141 | @Override |
| 139 | 142 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) |
| 140 | - public PageResult<CrmReceivableDO> getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO) { | |
| 141 | - return receivableMapper.selectPageByCustomer(pageReqVO); | |
| 143 | + public PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO) { | |
| 144 | + return receivableMapper.selectPageByCustomerId(pageReqVO); | |
| 145 | + } | |
| 146 | + | |
| 147 | + @Override | |
| 148 | + public void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId) { | |
| 149 | + // 1 校验回款是否存在 | |
| 150 | + validateReceivableExists(reqVO.getId()); | |
| 151 | + | |
| 152 | + // 2.1 数据权限转移 | |
| 153 | + crmPermissionService.transferPermission( | |
| 154 | + CrmReceivableConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType())); | |
| 155 | + // 2.2 设置新的负责人 | |
| 156 | + receivableMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | |
| 157 | + | |
| 158 | + // 3. TODO 记录转移日志 | |
| 142 | 159 | } |
| 143 | 160 | |
| 144 | 161 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java
| ... | ... | @@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil; |
| 6 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 8 | 8 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; |
| 9 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | |
| 9 | 10 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 10 | 11 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 11 | 12 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| ... | ... | @@ -17,7 +18,7 @@ import java.util.List; |
| 17 | 18 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 18 | 19 | |
| 19 | 20 | /** |
| 20 | - * CRM 分页查询工具类 | |
| 21 | + * CRM 查询工具类 | |
| 21 | 22 | * |
| 22 | 23 | * @author HUIHUI |
| 23 | 24 | */ |
| ... | ... | @@ -26,17 +27,17 @@ public class CrmQueryWrapperUtils { |
| 26 | 27 | /** |
| 27 | 28 | * 构造 CRM 数据类型数据分页查询条件 |
| 28 | 29 | * |
| 29 | - * @param query 连表查询对象 | |
| 30 | - * @param bizType 数据类型 {@link CrmBizTypeEnum} | |
| 31 | - * @param bizId 数据编号 | |
| 32 | - * @param userId 用户编号 | |
| 33 | - * @param sceneType 场景类型 | |
| 34 | - * @param pool 公海 | |
| 30 | + * @param query 连表查询对象 | |
| 31 | + * @param bizType 数据类型 {@link CrmBizTypeEnum} | |
| 32 | + * @param bizId 数据编号 | |
| 33 | + * @param userId 用户编号 | |
| 34 | + * @param sceneType 场景类型 | |
| 35 | + * @param pool 公海 | |
| 36 | + * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) | |
| 35 | 37 | */ |
| 36 | - // TODO @puhui999:bizId 直接传递会不会简单点 | |
| 37 | - // TODO @puhui999:builderPageQuery 应该不仅仅适合于分页查询,应该适用于所有的查询;可以改成 appendPermissionCondition | |
| 38 | - public static <T extends MPJLambdaWrapper<?>, S> void builderPageQuery(T query, Integer bizType, SFunction<S, ?> bizId, | |
| 39 | - Long userId, Integer sceneType, Boolean pool) { | |
| 38 | + // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少 | |
| 39 | + public static <T extends MPJLambdaWrapper<?>, S> boolean appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, | |
| 40 | + Long userId, Integer sceneType, Boolean pool) { | |
| 40 | 41 | // 1. 构建数据权限连表条件 |
| 41 | 42 | if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 |
| 42 | 43 | query.innerJoin(CrmPermissionDO.class, on -> |
| ... | ... | @@ -48,52 +49,55 @@ public class CrmQueryWrapperUtils { |
| 48 | 49 | query.eq("owner_user_id", userId); |
| 49 | 50 | } |
| 50 | 51 | // 2.2 场景二:我参与的数据 |
| 51 | - // TODO @puhui999:参与,指的是有读写权限噢;可以把 1. 的合并到 2.2 里;因为 2.1 不需要; | |
| 52 | 52 | if (CrmSceneTypeEnum.isInvolved(sceneType)) { |
| 53 | - query.ne("owner_user_id", userId); | |
| 53 | + query | |
| 54 | + .ne("owner_user_id", userId) | |
| 55 | + .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) | |
| 56 | + .or() | |
| 57 | + .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); | |
| 58 | + | |
| 54 | 59 | } |
| 55 | 60 | // 2.3 场景三:下属负责的数据 |
| 56 | 61 | if (CrmSceneTypeEnum.isSubordinate(sceneType)) { |
| 57 | 62 | List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); |
| 58 | - // TODO @puhui999:如果为空,不拼接,就是查询了所有数据呀? | |
| 59 | - if (CollUtil.isNotEmpty(subordinateUsers)) { | |
| 60 | - query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); | |
| 63 | + if (CollUtil.isEmpty(subordinateUsers)) { | |
| 64 | + return false; | |
| 61 | 65 | } |
| 66 | + query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); | |
| 62 | 67 | } |
| 63 | 68 | |
| 64 | - // 2. 拼接公海的查询条件 | |
| 69 | + // 3. 拼接公海的查询条件 | |
| 65 | 70 | if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 |
| 66 | 71 | query.isNull("owner_user_id"); |
| 67 | 72 | } else { // 情况二:不是公海 |
| 68 | 73 | query.isNotNull("owner_user_id"); |
| 69 | 74 | } |
| 75 | + | |
| 76 | + return true; | |
| 70 | 77 | } |
| 71 | 78 | |
| 72 | 79 | /** |
| 73 | 80 | * 构造 CRM 数据类型批量数据查询条件 |
| 74 | 81 | * |
| 75 | - * @param query 连表查询对象 | |
| 76 | - * @param bizType 数据类型 {@link CrmBizTypeEnum} | |
| 77 | - * @param bizIds 数据编号 | |
| 78 | - * @param userId 用户编号 | |
| 82 | + * @param query 连表查询对象 | |
| 83 | + * @param bizType 数据类型 {@link CrmBizTypeEnum} | |
| 84 | + * @param bizIds 数据编号 | |
| 85 | + * @param userId 用户编号 | |
| 79 | 86 | */ |
| 80 | - // TODO @puhui999:可以改成 appendPermissionCondition | |
| 81 | - // TODO @puhui999:S 是不是可以删除 | |
| 82 | - public static <T extends MPJLambdaWrapper<?>, S> void builderListQueryBatch(T query, Integer bizType, Collection<Long> bizIds, Long userId) { | |
| 83 | - // TODO @puhui999:这里先 if return 简单点 | |
| 84 | - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 | |
| 85 | - query.innerJoin(CrmPermissionDO.class, on -> | |
| 86 | - on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) | |
| 87 | - .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); | |
| 87 | + public static <T extends MPJLambdaWrapper<?>> void appendPermissionCondition(T query, Integer bizType, Collection<Long> bizIds, Long userId) { | |
| 88 | + if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限 | |
| 89 | + return; | |
| 88 | 90 | } |
| 91 | + | |
| 92 | + query.innerJoin(CrmPermissionDO.class, on -> | |
| 93 | + on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) | |
| 94 | + .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); | |
| 89 | 95 | } |
| 90 | 96 | |
| 91 | - // TODO @puhui999:需要加个变量,不用每次都拿哈; | |
| 92 | 97 | private static AdminUserApi getAdminUserApi() { |
| 93 | - return SpringUtil.getBean(AdminUserApi.class); | |
| 98 | + return AdminUserApiHolder.ADMIN_USER_API; | |
| 94 | 99 | } |
| 95 | 100 | |
| 96 | - // TODO @puhui999:需要实现; | |
| 97 | 101 | /** |
| 98 | 102 | * 校验用户是否是管理员 |
| 99 | 103 | * |
| ... | ... | @@ -101,7 +105,27 @@ public class CrmQueryWrapperUtils { |
| 101 | 105 | * @return 是/否 |
| 102 | 106 | */ |
| 103 | 107 | private static boolean validateAdminUser(Long userId) { |
| 108 | + // TODO 查询权限配置表用户的角色信息 | |
| 109 | + //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); | |
| 110 | + //if (permissionConfig == null) { | |
| 111 | + // return false; | |
| 112 | + //} | |
| 113 | + //// 校验是否为管理员 | |
| 114 | + //if (permissionConfig.getIsAdmin()){ | |
| 115 | + // return true; | |
| 116 | + //} | |
| 104 | 117 | return false; |
| 105 | 118 | } |
| 106 | 119 | |
| 120 | + /** | |
| 121 | + * 静态内部类实现 AdminUserApi 单例获取 | |
| 122 | + * | |
| 123 | + * @author HUIHUI | |
| 124 | + */ | |
| 125 | + private static class AdminUserApiHolder { | |
| 126 | + | |
| 127 | + private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); | |
| 128 | + | |
| 129 | + } | |
| 130 | + | |
| 107 | 131 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java
| ... | ... | @@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv |
| 7 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 9 | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; |
| 10 | +import jakarta.annotation.Resource; | |
| 10 | 11 | import org.junit.jupiter.api.Disabled; |
| 11 | 12 | import org.junit.jupiter.api.Test; |
| 12 | 13 | import org.springframework.context.annotation.Import; |
| 13 | 14 | |
| 14 | -import jakarta.annotation.Resource; | |
| 15 | - | |
| 15 | +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | |
| 16 | 16 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 17 | 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 18 | 18 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| ... | ... | @@ -22,6 +22,7 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PL |
| 22 | 22 | import static org.junit.jupiter.api.Assertions.*; |
| 23 | 23 | |
| 24 | 24 | // TODO 芋艿:后续,需要补充测试用例 |
| 25 | + | |
| 25 | 26 | /** |
| 26 | 27 | * {@link CrmReceivablePlanServiceImpl} 的单元测试类 |
| 27 | 28 | * |
| ... | ... | @@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { |
| 43 | 44 | CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class); |
| 44 | 45 | |
| 45 | 46 | // 调用 |
| 46 | - Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO); | |
| 47 | + Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO, 1L); | |
| 47 | 48 | // 断言 |
| 48 | 49 | assertNotNull(receivablePlanId); |
| 49 | 50 | // 校验记录的属性是否正确 |
| ... | ... | @@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { |
| 87 | 88 | |
| 88 | 89 | // 调用 |
| 89 | 90 | receivablePlanService.deleteReceivablePlan(id); |
| 90 | - // 校验数据不存在了 | |
| 91 | - assertNull(crmReceivablePlanMapper.selectById(id)); | |
| 91 | + // 校验数据不存在了 | |
| 92 | + assertNull(crmReceivablePlanMapper.selectById(id)); | |
| 92 | 93 | } |
| 93 | 94 | |
| 94 | 95 | @Test |
| ... | ... | @@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { |
| 103 | 104 | @Test |
| 104 | 105 | @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 |
| 105 | 106 | public void testGetReceivablePlanPage() { |
| 106 | - // mock 数据 | |
| 107 | - CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到 | |
| 108 | - o.setPeriod(null); | |
| 109 | - o.setReturnTime(null); | |
| 110 | - o.setRemindDays(null); | |
| 111 | - o.setRemindTime(null); | |
| 112 | - o.setCustomerId(null); | |
| 113 | - o.setContractId(null); | |
| 114 | - o.setOwnerUserId(null); | |
| 115 | - o.setRemark(null); | |
| 116 | - o.setCreateTime(null); | |
| 117 | - }); | |
| 118 | - crmReceivablePlanMapper.insert(dbReceivablePlan); | |
| 119 | - // 测试 customerId 不匹配 | |
| 120 | - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); | |
| 121 | - // 测试 contractId 不匹配 | |
| 122 | - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); | |
| 123 | - // 准备参数 | |
| 124 | - CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO(); | |
| 125 | - reqVO.setCustomerId(null); | |
| 126 | - reqVO.setContractId(null); | |
| 127 | - | |
| 128 | - // 调用 | |
| 129 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO); | |
| 130 | - // 断言 | |
| 131 | - assertEquals(1, pageResult.getTotal()); | |
| 132 | - assertEquals(1, pageResult.getList().size()); | |
| 133 | - assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); | |
| 107 | + // mock 数据 | |
| 108 | + CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到 | |
| 109 | + o.setPeriod(null); | |
| 110 | + o.setReturnTime(null); | |
| 111 | + o.setRemindDays(null); | |
| 112 | + o.setRemindTime(null); | |
| 113 | + o.setCustomerId(null); | |
| 114 | + o.setContractId(null); | |
| 115 | + o.setOwnerUserId(null); | |
| 116 | + o.setRemark(null); | |
| 117 | + o.setCreateTime(null); | |
| 118 | + }); | |
| 119 | + crmReceivablePlanMapper.insert(dbReceivablePlan); | |
| 120 | + // 测试 customerId 不匹配 | |
| 121 | + crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); | |
| 122 | + // 测试 contractId 不匹配 | |
| 123 | + crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); | |
| 124 | + // 准备参数 | |
| 125 | + CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO(); | |
| 126 | + reqVO.setCustomerId(null); | |
| 127 | + reqVO.setContractId(null); | |
| 128 | + reqVO.setPageSize(PAGE_SIZE_NONE); | |
| 129 | + // 调用 | |
| 130 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO, 1L); | |
| 131 | + // 断言 | |
| 132 | + assertEquals(1, pageResult.getTotal()); | |
| 133 | + assertEquals(1, pageResult.getList().size()); | |
| 134 | + assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); | |
| 134 | 135 | } |
| 135 | 136 | |
| 136 | 137 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java
| ... | ... | @@ -7,12 +7,11 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.Crm |
| 7 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 9 | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; |
| 10 | +import jakarta.annotation.Resource; | |
| 10 | 11 | import org.junit.jupiter.api.Disabled; |
| 11 | 12 | import org.junit.jupiter.api.Test; |
| 12 | 13 | import org.springframework.context.annotation.Import; |
| 13 | 14 | |
| 14 | -import jakarta.annotation.Resource; | |
| 15 | - | |
| 16 | 15 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 17 | 16 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 18 | 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| ... | ... | @@ -133,7 +132,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest { |
| 133 | 132 | reqVO.setCustomerId(null); |
| 134 | 133 | |
| 135 | 134 | // 调用 |
| 136 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(reqVO); | |
| 135 | + PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(reqVO, 1L); | |
| 137 | 136 | // 断言 |
| 138 | 137 | assertEquals(1, pageResult.getTotal()); |
| 139 | 138 | assertEquals(1, pageResult.getList().size()); | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm
| ... | ... | @@ -63,7 +63,7 @@ export function export${simpleClassName}Excel(params) { |
| 63 | 63 | responseType: 'blob' |
| 64 | 64 | }) |
| 65 | 65 | } |
| 66 | -## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对 | |
| 66 | +## 特殊:主子表专属逻辑 | |
| 67 | 67 | #foreach ($subTable in $subTables) |
| 68 | 68 | #set ($index = $foreach.count - 1) |
| 69 | 69 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) |
| ... | ... | @@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) { |
| 76 | 76 | |
| 77 | 77 | // ==================== 子表($subTable.classComment) ==================== |
| 78 | 78 | ## 情况一:MASTER_ERP 时,需要分查询页子表 |
| 79 | - #if ( $table.templateType == 11 ) | |
| 79 | + #if ($table.templateType == 11) | |
| 80 | 80 | // 获得${subTable.classComment}分页 |
| 81 | 81 | export function get${subSimpleClassName}Page(params) { |
| 82 | 82 | return request({ |
| ... | ... | @@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) { |
| 87 | 87 | } |
| 88 | 88 | ## 情况二:非 MASTER_ERP 时,需要列表查询子表 |
| 89 | 89 | #else |
| 90 | - #if ( $subTable.subJoinMany ) | |
| 90 | + #if ($subTable.subJoinMany) | |
| 91 | 91 | // 获得${subTable.classComment}列表 |
| 92 | 92 | export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { |
| 93 | 93 | return request({ |
| ... | ... | @@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) { |
| 106 | 106 | #end |
| 107 | 107 | #end |
| 108 | 108 | ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 |
| 109 | - #if ( $table.templateType == 11 ) | |
| 109 | + #if ($table.templateType == 11) | |
| 110 | 110 | // 新增${subTable.classComment} |
| 111 | 111 | export function create${subSimpleClassName}(data) { |
| 112 | 112 | return request({ |
| ... | ... | @@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) { |
| 115 | 115 | data |
| 116 | 116 | }) |
| 117 | 117 | } |
| 118 | - | |
| 119 | 118 | // 修改${subTable.classComment} |
| 120 | 119 | export function update${subSimpleClassName}(data) { |
| 121 | 120 | return request({ |
| ... | ... | @@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) { |
| 124 | 123 | data |
| 125 | 124 | }) |
| 126 | 125 | } |
| 127 | - | |
| 128 | 126 | // 删除${subTable.classComment} |
| 129 | 127 | export function delete${subSimpleClassName}(id) { |
| 130 | 128 | return request({ |
| ... | ... | @@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) { |
| 132 | 130 | method: 'delete' |
| 133 | 131 | }) |
| 134 | 132 | } |
| 135 | - | |
| 136 | 133 | // 获得${subTable.classComment} |
| 137 | 134 | export function get${subSimpleClassName}(id) { |
| 138 | 135 | return request({ | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
| ... | ... | @@ -7,11 +7,10 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity |
| 7 | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| 8 | 8 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; |
| 9 | 9 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; |
| 10 | +import jakarta.annotation.Resource; | |
| 10 | 11 | import org.springframework.stereotype.Service; |
| 11 | 12 | import org.springframework.validation.annotation.Validated; |
| 12 | 13 | |
| 13 | -import jakarta.annotation.Resource; | |
| 14 | - | |
| 15 | 14 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 16 | 15 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS; |
| 17 | 16 | |
| ... | ... | @@ -25,21 +24,21 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA |
| 25 | 24 | public class CombinationRecordApiImpl implements CombinationRecordApi { |
| 26 | 25 | |
| 27 | 26 | @Resource |
| 28 | - private CombinationRecordService recordService; | |
| 27 | + private CombinationRecordService combinationRecordService; | |
| 29 | 28 | |
| 30 | 29 | @Override |
| 31 | 30 | public void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count) { |
| 32 | - recordService.validateCombinationRecord(userId, activityId, headId, skuId, count); | |
| 31 | + combinationRecordService.validateCombinationRecord(userId, activityId, headId, skuId, count); | |
| 33 | 32 | } |
| 34 | 33 | |
| 35 | 34 | @Override |
| 36 | 35 | public CombinationRecordCreateRespDTO createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 37 | - return CombinationActivityConvert.INSTANCE.convert4(recordService.createCombinationRecord(reqDTO)); | |
| 36 | + return CombinationActivityConvert.INSTANCE.convert4(combinationRecordService.createCombinationRecord(reqDTO)); | |
| 38 | 37 | } |
| 39 | 38 | |
| 40 | 39 | @Override |
| 41 | 40 | public boolean isCombinationRecordSuccess(Long userId, Long orderId) { |
| 42 | - CombinationRecordDO record = recordService.getCombinationRecord(userId, orderId); | |
| 41 | + CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId); | |
| 43 | 42 | if (record == null) { |
| 44 | 43 | throw exception(COMBINATION_RECORD_NOT_EXISTS); |
| 45 | 44 | } |
| ... | ... | @@ -48,7 +47,7 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { |
| 48 | 47 | |
| 49 | 48 | @Override |
| 50 | 49 | public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) { |
| 51 | - return recordService.validateJoinCombination(userId, activityId, headId, skuId, count); | |
| 50 | + return combinationRecordService.validateJoinCombination(userId, activityId, headId, skuId, count); | |
| 52 | 51 | } |
| 53 | 52 | |
| 54 | 53 | } | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java
| ... | ... | @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.util.ObjUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 7 | +import cn.iocoder.yudao.framework.common.util.date.DateUtils; | |
| 7 | 8 | import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; |
| 8 | 9 | import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; |
| 9 | 10 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; |
| ... | ... | @@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert { |
| 47 | 48 | // 1. 计算是第几天签到 |
| 48 | 49 | configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); |
| 49 | 50 | MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置 |
| 50 | - // 1.2. 计算今天是第几天签到 | |
| 51 | + // 1.2. 计算今天是第几天签到 (只有连续签到才加否则重置为 1) | |
| 51 | 52 | int day = 1; |
| 52 | - // TODO @puhui999:要判断是不是昨天签到的;是否是昨天的判断,可以抽个方法到 util 里 | |
| 53 | - if (lastRecord != null) { | |
| 53 | + if (lastRecord != null && DateUtils.isYesterday(lastRecord.getCreateTime())) { | |
| 54 | 54 | day = lastRecord.getDay() + 1; |
| 55 | 55 | } |
| 56 | 56 | // 1.3 判断是否超出了最大签到配置 | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java
| ... | ... | @@ -19,14 +19,12 @@ import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; |
| 19 | 19 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; |
| 20 | 20 | import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; |
| 21 | 21 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 22 | +import jakarta.annotation.Resource; | |
| 22 | 23 | import org.apache.commons.lang3.StringUtils; |
| 23 | 24 | import org.springframework.stereotype.Service; |
| 24 | 25 | import org.springframework.transaction.annotation.Transactional; |
| 25 | 26 | import org.springframework.validation.annotation.Validated; |
| 26 | 27 | |
| 27 | -import jakarta.annotation.Resource; | |
| 28 | -import java.time.LocalDate; | |
| 29 | -import java.util.Comparator; | |
| 30 | 28 | import java.util.List; |
| 31 | 29 | import java.util.Set; |
| 32 | 30 | |
| ... | ... | @@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService |
| 77 | 75 | } |
| 78 | 76 | summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime())); |
| 79 | 77 | |
| 80 | - // 4. 校验今天是否签到,没有签到则直接返回 | |
| 78 | + // 4.1 校验今天是否签到,没有签到则直接返回 | |
| 81 | 79 | if (!summary.getTodaySignIn()) { |
| 82 | 80 | return summary; |
| 83 | 81 | } |
| 84 | - // 4.1. 判断连续签到天数 | |
| 85 | - // TODO @puhui999:连续签到,可以基于 lastRecord 的 day 和当前时间判断呀?按 day 统计连续签到天数可能不准确 | |
| 86 | - // 1. day 只是记录第几天签到的有可能不连续,比如第一次签到是周一,第二次签到是周三这样 lastRecord 的 day 为 2 但是并不是连续的两天 | |
| 87 | - // 2. day 超出签到规则的最大天数会重置到从第一天开始签到(我理解为开始下一轮,类似一周签到七天七天结束下周又从周一开始签到) | |
| 88 | - // 1. 回复:周三签到,day 要归 1 呀。连续签到哈; | |
| 89 | - List<MemberSignInRecordDO> signInRecords = signInRecordMapper.selectListByUserId(userId); | |
| 90 | - signInRecords.sort(Comparator.comparing(MemberSignInRecordDO::getCreateTime).reversed()); // 根据签到时间倒序 | |
| 91 | - summary.setContinuousDay(calculateConsecutiveDays(signInRecords)); | |
| 82 | + // 4.2 连续签到天数 | |
| 83 | + summary.setContinuousDay(lastRecord.getDay()); | |
| 92 | 84 | return summary; |
| 93 | 85 | } |
| 94 | 86 | |
| 95 | - /** | |
| 96 | - * 计算连续签到天数 | |
| 97 | - * | |
| 98 | - * @param signInRecords 签到记录列表 | |
| 99 | - * @return int 连续签到天数 | |
| 100 | - */ | |
| 101 | - public int calculateConsecutiveDays(List<MemberSignInRecordDO> signInRecords) { | |
| 102 | - int consecutiveDays = 1; // 初始连续天数为1 | |
| 103 | - LocalDate previousDate = null; | |
| 104 | - | |
| 105 | - for (MemberSignInRecordDO record : signInRecords) { | |
| 106 | - LocalDate currentDate = record.getCreateTime().toLocalDate(); | |
| 107 | - | |
| 108 | - if (previousDate != null) { | |
| 109 | - // 检查相邻两个日期是否连续 | |
| 110 | - if (currentDate.minusDays(1).isEqual(previousDate)) { | |
| 111 | - consecutiveDays++; | |
| 112 | - } else { | |
| 113 | - // 如果日期不连续,停止遍历 | |
| 114 | - break; | |
| 115 | - } | |
| 116 | - } | |
| 117 | - | |
| 118 | - previousDate = currentDate; | |
| 119 | - } | |
| 120 | - | |
| 121 | - return consecutiveDays; | |
| 122 | - } | |
| 123 | - | |
| 124 | 87 | @Override |
| 125 | 88 | public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { |
| 126 | 89 | // 根据用户昵称查询出用户ids | ... | ... |
yudao-module-system/yudao-module-system-api/pom.xml
| ... | ... | @@ -22,6 +22,23 @@ |
| 22 | 22 | <artifactId>yudao-common</artifactId> |
| 23 | 23 | </dependency> |
| 24 | 24 | |
| 25 | + <!-- Springboot-注解-通用操作日志组件 --> | |
| 26 | + <!-- 此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 --> | |
| 27 | + <dependency> | |
| 28 | + <groupId>io.github.mouzt</groupId> | |
| 29 | + <artifactId>bizlog-sdk</artifactId> | |
| 30 | + </dependency> | |
| 31 | + | |
| 32 | + <!--工具类相关--> | |
| 33 | + <dependency> | |
| 34 | + <groupId>com.fasterxml.jackson.core</groupId> | |
| 35 | + <artifactId>jackson-databind</artifactId> | |
| 36 | + </dependency> | |
| 37 | + <dependency> | |
| 38 | + <groupId>com.fasterxml.jackson.core</groupId> | |
| 39 | + <artifactId>jackson-core</artifactId> | |
| 40 | + </dependency> | |
| 41 | + | |
| 25 | 42 | <!-- 参数校验 --> |
| 26 | 43 | <dependency> |
| 27 | 44 | <groupId>org.springframework.boot</groupId> | ... | ... |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
| 1 | 1 | package cn.iocoder.yudao.module.system.api.logger; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 4 | - | |
| 4 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | |
| 5 | 5 | import jakarta.validation.Valid; |
| 6 | 6 | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 7 | 9 | /** |
| 8 | 10 | * 操作日志 API 接口 |
| 9 | 11 | * |
| ... | ... | @@ -18,4 +20,13 @@ public interface OperateLogApi { |
| 18 | 20 | */ |
| 19 | 21 | void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); |
| 20 | 22 | |
| 23 | + /** | |
| 24 | + * 获取指定模块的指定数据的操作日志 | |
| 25 | + * | |
| 26 | + * @param module 操作模块 | |
| 27 | + * @param bizId 操作模块编号 | |
| 28 | + * @return 操作日志 | |
| 29 | + */ | |
| 30 | + List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId); | |
| 31 | + | |
| 21 | 32 | } | ... | ... |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.logger.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | |
| 4 | +import com.fasterxml.jackson.annotation.JsonFormat; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | + | |
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 系统操作日志 Resp DTO | |
| 14 | + * | |
| 15 | + * @author HUIHUI | |
| 16 | + */ | |
| 17 | +@Data | |
| 18 | +public class OperateLogV2RespDTO { | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 链路追踪编号 | |
| 22 | + * | |
| 23 | + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 | |
| 24 | + */ | |
| 25 | + private String traceId; | |
| 26 | + /** | |
| 27 | + * 用户编号 | |
| 28 | + * | |
| 29 | + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 | |
| 30 | + */ | |
| 31 | + private Long userId; | |
| 32 | + /** | |
| 33 | + * 用户类型 | |
| 34 | + * | |
| 35 | + * 关联 {@link UserTypeEnum} | |
| 36 | + */ | |
| 37 | + private Integer userType; | |
| 38 | + /** | |
| 39 | + * 操作模块 | |
| 40 | + */ | |
| 41 | + private String module; | |
| 42 | + /** | |
| 43 | + * 操作名 | |
| 44 | + */ | |
| 45 | + private String name; | |
| 46 | + /** | |
| 47 | + * 操作模块业务编号 | |
| 48 | + */ | |
| 49 | + private Long bizId; | |
| 50 | + /** | |
| 51 | + * 操作内容,记录整个操作的明细 | |
| 52 | + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | |
| 53 | + */ | |
| 54 | + private String content; | |
| 55 | + /** | |
| 56 | + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) | |
| 57 | + * 例如说,记录订单编号,{ orderId: "1"} | |
| 58 | + */ | |
| 59 | + private String extra; | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * 请求方法名 | |
| 63 | + */ | |
| 64 | + private String requestMethod; | |
| 65 | + /** | |
| 66 | + * 请求地址 | |
| 67 | + */ | |
| 68 | + private String requestUrl; | |
| 69 | + /** | |
| 70 | + * 用户 IP | |
| 71 | + */ | |
| 72 | + private String userIp; | |
| 73 | + /** | |
| 74 | + * 浏览器 UA | |
| 75 | + */ | |
| 76 | + private String userAgent; | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 创建时间 | |
| 80 | + */ | |
| 81 | + // TODO puhui999: 木得效果怎么肥事 | |
| 82 | + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) | |
| 83 | + private LocalDateTime createTime; | |
| 84 | + /** | |
| 85 | + * 创建者,关联 AdminUserDO#getId | |
| 86 | + */ | |
| 87 | + private String creator; | |
| 88 | + /** | |
| 89 | + * 创建者名称 | |
| 90 | + */ | |
| 91 | + private String creatorName; | |
| 92 | + | |
| 93 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.system.api.logger; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 3 | 5 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 6 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | |
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 4 | 9 | import cn.iocoder.yudao.module.system.service.logger.OperateLogService; |
| 10 | +import cn.iocoder.yudao.module.system.service.user.AdminUserService; | |
| 11 | +import jakarta.annotation.Resource; | |
| 5 | 12 | import org.springframework.stereotype.Service; |
| 6 | 13 | import org.springframework.validation.annotation.Validated; |
| 7 | 14 | |
| 8 | -import jakarta.annotation.Resource; | |
| 15 | +import java.util.Collections; | |
| 16 | +import java.util.List; | |
| 17 | +import java.util.Map; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | |
| 9 | 21 | |
| 10 | 22 | /** |
| 11 | 23 | * 操作日志 API 实现类 |
| ... | ... | @@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi { |
| 18 | 30 | |
| 19 | 31 | @Resource |
| 20 | 32 | private OperateLogService operateLogService; |
| 33 | + @Resource | |
| 34 | + private AdminUserService adminUserService; | |
| 21 | 35 | |
| 22 | 36 | @Override |
| 23 | 37 | public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { |
| 24 | 38 | operateLogService.createOperateLog(createReqDTO); |
| 25 | 39 | } |
| 26 | 40 | |
| 41 | + @Override | |
| 42 | + public List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId) { | |
| 43 | + List<OperateLogV2DO> logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId); | |
| 44 | + if (CollUtil.isEmpty(logList)) { | |
| 45 | + return Collections.emptyList(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + // 获取用户 | |
| 49 | + List<AdminUserDO> userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator()))); | |
| 50 | + Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId); | |
| 51 | + return convertList(logList, item -> { | |
| 52 | + OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class); | |
| 53 | + findAndThen(userMap, Long.parseLong(item.getCreator()), user -> { | |
| 54 | + bean.setCreatorName(user.getNickname()); | |
| 55 | + }); | |
| 56 | + return bean; | |
| 57 | + }); | |
| 58 | + } | |
| 59 | + | |
| 27 | 60 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.logger; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 5 | +import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 6 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 7 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 8 | +import lombok.Data; | |
| 9 | +import lombok.EqualsAndHashCode; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 操作日志表 V2 | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@TableName(value = "system_operate_log_v2", autoResultMap = true) | |
| 17 | +@KeySequence("system_operate_log_seq_v2") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 18 | +@Data | |
| 19 | +@EqualsAndHashCode(callSuper = true) | |
| 20 | +public class OperateLogV2DO extends BaseDO { | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 日志主键 | |
| 24 | + */ | |
| 25 | + @TableId | |
| 26 | + private Long id; | |
| 27 | + /** | |
| 28 | + * 链路追踪编号 | |
| 29 | + * | |
| 30 | + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 | |
| 31 | + */ | |
| 32 | + private String traceId; | |
| 33 | + /** | |
| 34 | + * 用户编号 | |
| 35 | + * | |
| 36 | + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 | |
| 37 | + */ | |
| 38 | + private Long userId; | |
| 39 | + /** | |
| 40 | + * 用户类型 | |
| 41 | + * | |
| 42 | + * 关联 {@link UserTypeEnum} | |
| 43 | + */ | |
| 44 | + private Integer userType; | |
| 45 | + /** | |
| 46 | + * 操作模块 | |
| 47 | + */ | |
| 48 | + private String module; | |
| 49 | + /** | |
| 50 | + * 操作名 | |
| 51 | + */ | |
| 52 | + private String name; | |
| 53 | + /** | |
| 54 | + * 操作模块业务编号 | |
| 55 | + */ | |
| 56 | + private Long bizId; | |
| 57 | + /** | |
| 58 | + * 操作内容,记录整个操作的明细 | |
| 59 | + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | |
| 60 | + */ | |
| 61 | + private String content; | |
| 62 | + /** | |
| 63 | + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) | |
| 64 | + * 例如说,记录订单编号,{ orderId: "1"} | |
| 65 | + */ | |
| 66 | + private String extra; | |
| 67 | + /** | |
| 68 | + * 请求方法名 | |
| 69 | + */ | |
| 70 | + private String requestMethod; | |
| 71 | + /** | |
| 72 | + * 请求地址 | |
| 73 | + */ | |
| 74 | + private String requestUrl; | |
| 75 | + /** | |
| 76 | + * 用户 IP | |
| 77 | + */ | |
| 78 | + private String userIp; | |
| 79 | + /** | |
| 80 | + * 浏览器 UA | |
| 81 | + */ | |
| 82 | + private String userAgent; | |
| 83 | + | |
| 84 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.mysql.logger; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | |
| 8 | +import org.apache.ibatis.annotations.Mapper; | |
| 9 | + | |
| 10 | +import java.util.Collection; | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +@Mapper | |
| 14 | +public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> { | |
| 15 | + | |
| 16 | + default PageResult<OperateLogV2DO> selectPage(OperateLogPageReqVO reqVO, Collection<Long> userIds) { | |
| 17 | + LambdaQueryWrapperX<OperateLogV2DO> query = new LambdaQueryWrapperX<OperateLogV2DO>() | |
| 18 | + .likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule()) | |
| 19 | + .inIfPresent(OperateLogV2DO::getUserId, userIds); | |
| 20 | + query.orderByDesc(OperateLogV2DO::getId); // 降序 | |
| 21 | + return selectPage(reqVO, query); | |
| 22 | + } | |
| 23 | + | |
| 24 | + default List<OperateLogV2DO> selectListByModuleAndBizId(String module, Long bizId) { | |
| 25 | + return selectList(new LambdaQueryWrapperX<OperateLogV2DO>() | |
| 26 | + .eq(OperateLogV2DO::getModule, module) | |
| 27 | + .eq(OperateLogV2DO::getBizId, bizId) | |
| 28 | + .orderByDesc(OperateLogV2DO::getCreateTime)); | |
| 29 | + } | |
| 30 | + | |
| 31 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.bizlog.config; | |
| 2 | + | |
| 3 | +import com.mzt.logapi.starter.annotation.EnableLogRecord; | |
| 4 | +import org.springframework.context.annotation.Configuration; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * mzt-biz-log 配置类 | |
| 8 | + * | |
| 9 | + * @author HUIHUI | |
| 10 | + */ | |
| 11 | +@Configuration(proxyBeanMethods = false) | |
| 12 | +@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 | |
| 13 | +public class YudaoOperateLogV2Configuration { | |
| 14 | + | |
| 15 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.bizlog.function; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 4 | +import cn.hutool.core.util.StrUtil; | |
| 5 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 6 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 7 | +import com.mzt.logapi.service.IParseFunction; | |
| 8 | +import jakarta.annotation.Resource; | |
| 9 | +import lombok.extern.slf4j.Slf4j; | |
| 10 | +import org.springframework.stereotype.Component; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 自定义函数-通过用户编号获取用户信息 | |
| 14 | + * | |
| 15 | + * @author HUIHUI | |
| 16 | + */ | |
| 17 | +@Slf4j | |
| 18 | +@Component | |
| 19 | +public class AdminUserParseFunction implements IParseFunction { | |
| 20 | + | |
| 21 | + @Resource | |
| 22 | + private AdminUserApi adminUserApi; | |
| 23 | + | |
| 24 | + @Override | |
| 25 | + public String functionName() { | |
| 26 | + return "getAdminUserById"; | |
| 27 | + } | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + public String apply(Object value) { | |
| 31 | + if (value == null) { | |
| 32 | + //log.warn("(getAdminUserById) 解析异常参数为 null"); | |
| 33 | + return ""; | |
| 34 | + } | |
| 35 | + if (StrUtil.isEmpty(value.toString())) { | |
| 36 | + //log.warn("(getAdminUserById) 解析异常参数为空"); | |
| 37 | + return ""; | |
| 38 | + } | |
| 39 | + | |
| 40 | + // 获取用户信息 | |
| 41 | + AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(value.toString())); | |
| 42 | + if (user == null) { | |
| 43 | + log.warn("(getAdminUserById) 获取用户信息失败,参数为:{}", value); | |
| 44 | + return ""; | |
| 45 | + } | |
| 46 | + // 返回格式 芋道源码(13888888888) | |
| 47 | + String nickname = user.getNickname(); | |
| 48 | + if (ObjUtil.isNotEmpty(user.getMobile())) { | |
| 49 | + return nickname.concat("(").concat(user.getMobile()).concat(")"); | |
| 50 | + } | |
| 51 | + return nickname; | |
| 52 | + } | |
| 53 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.bizlog.function; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; | |
| 5 | +import com.mzt.logapi.service.IParseFunction; | |
| 6 | +import lombok.extern.slf4j.Slf4j; | |
| 7 | +import org.springframework.stereotype.Component; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 自定义函数-通过区域编号获取区域信息 | |
| 11 | + * | |
| 12 | + * @author HUIHUI | |
| 13 | + */ | |
| 14 | +@Slf4j | |
| 15 | +@Component | |
| 16 | +public class AreaParseFunction implements IParseFunction { | |
| 17 | + | |
| 18 | + @Override | |
| 19 | + public boolean executeBefore() { | |
| 20 | + return true; // 先转换值后对比 | |
| 21 | + } | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public String functionName() { | |
| 25 | + return "getAreaById"; | |
| 26 | + } | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public String apply(Object value) { | |
| 30 | + if (value == null) { | |
| 31 | + return ""; | |
| 32 | + } | |
| 33 | + if (StrUtil.isEmpty(value.toString())) { | |
| 34 | + return ""; | |
| 35 | + } | |
| 36 | + | |
| 37 | + return AreaUtils.format(Integer.parseInt(value.toString())); | |
| 38 | + } | |
| 39 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java
0 → 100644
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.bizlog.service; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | |
| 5 | +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | |
| 6 | +import cn.iocoder.yudao.module.system.service.logger.OperateLogService; | |
| 7 | +import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | |
| 8 | +import com.mzt.logapi.beans.LogRecord; | |
| 9 | +import com.mzt.logapi.service.ILogRecordService; | |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | +import jakarta.servlet.http.HttpServletRequest; | |
| 12 | +import lombok.extern.slf4j.Slf4j; | |
| 13 | +import org.springframework.stereotype.Service; | |
| 14 | + | |
| 15 | +import java.util.Collections; | |
| 16 | +import java.util.List; | |
| 17 | + | |
| 18 | +/** | |
| 19 | + * 操作日志 ILogRecordService 实现类 | |
| 20 | + * | |
| 21 | + * 基于 {@link OperateLogService} 实现,记录操作日志 | |
| 22 | + * | |
| 23 | + * @author HUIHUI | |
| 24 | + */ | |
| 25 | +@Slf4j | |
| 26 | +@Service | |
| 27 | +public class ILogRecordServiceImpl implements ILogRecordService { | |
| 28 | + | |
| 29 | + @Resource | |
| 30 | + private OperateLogService operateLogService; | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public void record(LogRecord logRecord) { | |
| 34 | + OperateLogV2CreateReqBO reqBO = new OperateLogV2CreateReqBO(); | |
| 35 | + // 补全通用字段 | |
| 36 | + reqBO.setTraceId(TracerUtils.getTraceId()); | |
| 37 | + // 补充用户信息 | |
| 38 | + fillUserFields(reqBO); | |
| 39 | + // 补全模块信息 | |
| 40 | + fillModuleFields(reqBO, logRecord); | |
| 41 | + // 补全请求信息 | |
| 42 | + fillRequestFields(reqBO); | |
| 43 | + // 异步记录日志 | |
| 44 | + operateLogService.createOperateLogV2(reqBO); | |
| 45 | + log.info("操作日志 ===> {}", reqBO); | |
| 46 | + } | |
| 47 | + | |
| 48 | + private static void fillUserFields(OperateLogV2CreateReqBO reqBO) { | |
| 49 | + reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); | |
| 50 | + reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); | |
| 51 | + } | |
| 52 | + | |
| 53 | + public static void fillModuleFields(OperateLogV2CreateReqBO reqBO, LogRecord logRecord) { | |
| 54 | + reqBO.setModule(logRecord.getType()); // 大模块类型如 crm-客户 | |
| 55 | + reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户 | |
| 56 | + reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 | |
| 57 | + reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | |
| 58 | + reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} | |
| 59 | + } | |
| 60 | + | |
| 61 | + private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) { | |
| 62 | + // 获得 Request 对象 | |
| 63 | + HttpServletRequest request = ServletUtils.getRequest(); | |
| 64 | + if (request == null) { | |
| 65 | + return; | |
| 66 | + } | |
| 67 | + // 补全请求信息 | |
| 68 | + reqBO.setRequestMethod(request.getMethod()); | |
| 69 | + reqBO.setRequestUrl(request.getRequestURI()); | |
| 70 | + reqBO.setUserIp(ServletUtils.getClientIP(request)); | |
| 71 | + reqBO.setUserAgent(ServletUtils.getUserAgent(request)); | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Override | |
| 75 | + public List<LogRecord> queryLog(String bizNo, String type) { | |
| 76 | + return Collections.emptyList(); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public List<LogRecord> queryLogByBizNo(String bizNo, String type, String subType) { | |
| 81 | + return Collections.emptyList(); | |
| 82 | + } | |
| 83 | + | |
| 84 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java
| ... | ... | @@ -4,6 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 5 | 5 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | |
| 8 | +import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | |
| 9 | + | |
| 10 | +import java.util.List; | |
| 7 | 11 | |
| 8 | 12 | /** |
| 9 | 13 | * 操作日志 Service 接口 |
| ... | ... | @@ -27,4 +31,22 @@ public interface OperateLogService { |
| 27 | 31 | */ |
| 28 | 32 | PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO); |
| 29 | 33 | |
| 34 | + //======================= LOG V2 ======================= | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 记录操作日志 V2 | |
| 38 | + * | |
| 39 | + * @param createReqBO 创建请求 | |
| 40 | + */ | |
| 41 | + void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 获取指定模块的指定数据的操作日志 | |
| 45 | + * | |
| 46 | + * @param module 操作模块 | |
| 47 | + * @param bizId 操作模块编号 | |
| 48 | + * @return 操作日志 | |
| 49 | + */ | |
| 50 | + List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId); | |
| 51 | + | |
| 30 | 52 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java
| ... | ... | @@ -8,15 +8,19 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; |
| 8 | 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 9 | 9 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 10 | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; |
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | |
| 11 | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 12 | 13 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; |
| 14 | +import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper; | |
| 15 | +import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | |
| 13 | 16 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 17 | +import jakarta.annotation.Resource; | |
| 14 | 18 | import lombok.extern.slf4j.Slf4j; |
| 15 | 19 | import org.springframework.stereotype.Service; |
| 16 | 20 | import org.springframework.validation.annotation.Validated; |
| 17 | 21 | |
| 18 | -import jakarta.annotation.Resource; | |
| 19 | 22 | import java.util.Collection; |
| 23 | +import java.util.List; | |
| 20 | 24 | |
| 21 | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 22 | 26 | import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; |
| ... | ... | @@ -34,6 +38,8 @@ public class OperateLogServiceImpl implements OperateLogService { |
| 34 | 38 | |
| 35 | 39 | @Resource |
| 36 | 40 | private OperateLogMapper operateLogMapper; |
| 41 | + @Resource | |
| 42 | + private OperateLogV2Mapper operateLogV2Mapper; | |
| 37 | 43 | |
| 38 | 44 | @Resource |
| 39 | 45 | private AdminUserService userService; |
| ... | ... | @@ -60,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService { |
| 60 | 66 | return operateLogMapper.selectPage(pageReqVO, userIds); |
| 61 | 67 | } |
| 62 | 68 | |
| 69 | + //======================= LOG V2 ======================= | |
| 70 | + | |
| 71 | + @Override | |
| 72 | + public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { | |
| 73 | + OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); | |
| 74 | + operateLogV2Mapper.insert(log); | |
| 75 | + } | |
| 76 | + | |
| 77 | + @Override | |
| 78 | + public List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId) { | |
| 79 | + return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId); | |
| 80 | + } | |
| 81 | + | |
| 63 | 82 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.logger.bo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | |
| 4 | +import jakarta.validation.constraints.NotEmpty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 系统操作日志 Create Req BO | |
| 9 | + * | |
| 10 | + * @author HUIHUI | |
| 11 | + */ | |
| 12 | +@Data | |
| 13 | +public class OperateLogV2CreateReqBO { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 链路追踪编号 | |
| 17 | + * | |
| 18 | + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 | |
| 19 | + */ | |
| 20 | + private String traceId; | |
| 21 | + /** | |
| 22 | + * 用户编号 | |
| 23 | + * | |
| 24 | + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 | |
| 25 | + */ | |
| 26 | + @NotEmpty(message = "用户编号不能为空") | |
| 27 | + private Long userId; | |
| 28 | + /** | |
| 29 | + * 用户类型 | |
| 30 | + * | |
| 31 | + * 关联 {@link UserTypeEnum} | |
| 32 | + */ | |
| 33 | + @NotEmpty(message = "用户类型不能为空") | |
| 34 | + private Integer userType; | |
| 35 | + /** | |
| 36 | + * 操作模块 | |
| 37 | + */ | |
| 38 | + @NotEmpty(message = "操作模块不能为空") | |
| 39 | + private String module; | |
| 40 | + /** | |
| 41 | + * 操作名 | |
| 42 | + */ | |
| 43 | + @NotEmpty(message = "操作名不能为空") | |
| 44 | + private String name; | |
| 45 | + /** | |
| 46 | + * 操作模块业务编号 | |
| 47 | + */ | |
| 48 | + @NotEmpty(message = "操作模块业务编号不能为空") | |
| 49 | + private Long bizId; | |
| 50 | + /** | |
| 51 | + * 操作内容,记录整个操作的明细 | |
| 52 | + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | |
| 53 | + */ | |
| 54 | + @NotEmpty(message = "操作内容不能为空") | |
| 55 | + private String content; | |
| 56 | + /** | |
| 57 | + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) | |
| 58 | + * 例如说,记录订单编号,{ orderId: "1"} | |
| 59 | + */ | |
| 60 | + private String extra; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 请求方法名 | |
| 64 | + */ | |
| 65 | + @NotEmpty(message = "请求方法名不能为空") | |
| 66 | + private String requestMethod; | |
| 67 | + /** | |
| 68 | + * 请求地址 | |
| 69 | + */ | |
| 70 | + @NotEmpty(message = "请求地址不能为空") | |
| 71 | + private String requestUrl; | |
| 72 | + /** | |
| 73 | + * 用户 IP | |
| 74 | + */ | |
| 75 | + @NotEmpty(message = "用户 IP 不能为空") | |
| 76 | + private String userIp; | |
| 77 | + /** | |
| 78 | + * 浏览器 UA | |
| 79 | + */ | |
| 80 | + @NotEmpty(message = "浏览器 UA 不能为空") | |
| 81 | + private String userAgent; | |
| 82 | + | |
| 83 | +} | ... | ... |