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,6 +62,7 @@ | ||
| 62 | <jsch.version>0.1.55</jsch.version> | 62 | <jsch.version>0.1.55</jsch.version> |
| 63 | <tika-core.version>2.9.1</tika-core.version> | 63 | <tika-core.version>2.9.1</tika-core.version> |
| 64 | <ip2region.version>2.7.0</ip2region.version> | 64 | <ip2region.version>2.7.0</ip2region.version> |
| 65 | + <bizlog-sdk.version>3.0.6</bizlog-sdk.version> | ||
| 65 | <!-- 三方云服务相关 --> | 66 | <!-- 三方云服务相关 --> |
| 66 | <okio.version>3.5.0</okio.version> | 67 | <okio.version>3.5.0</okio.version> |
| 67 | <okhttp3.version>4.11.0</okhttp3.version> | 68 | <okhttp3.version>4.11.0</okhttp3.version> |
| @@ -100,6 +101,17 @@ | @@ -100,6 +101,17 @@ | ||
| 100 | <version>${revision}</version> | 101 | <version>${revision}</version> |
| 101 | </dependency> | 102 | </dependency> |
| 102 | <dependency> | 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 | <groupId>cn.iocoder.boot</groupId> | 115 | <groupId>cn.iocoder.boot</groupId> |
| 104 | <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | 116 | <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> |
| 105 | <version>${revision}</version> | 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,4 +177,14 @@ public class DateUtils { | ||
| 177 | return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now()); | 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,7 +22,9 @@ public enum CrmBizTypeEnum implements IntArrayValuable { | ||
| 22 | CRM_CONTACT(3, "联系人"), | 22 | CRM_CONTACT(3, "联系人"), |
| 23 | CRM_BUSINESS(4, "商机"), | 23 | CRM_BUSINESS(4, "商机"), |
| 24 | CRM_CONTRACT(5, "合同"), | 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 | public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray(); | 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,6 +60,10 @@ | ||
| 60 | <groupId>cn.iocoder.boot</groupId> | 60 | <groupId>cn.iocoder.boot</groupId> |
| 61 | <artifactId>yudao-spring-boot-starter-excel</artifactId> | 61 | <artifactId>yudao-spring-boot-starter-excel</artifactId> |
| 62 | </dependency> | 62 | </dependency> |
| 63 | + <dependency> | ||
| 64 | + <groupId>cn.iocoder.boot</groupId> | ||
| 65 | + <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | ||
| 66 | + </dependency> | ||
| 63 | 67 | ||
| 64 | <!-- Test 测试相关 --> | 68 | <!-- Test 测试相关 --> |
| 65 | <dependency> | 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,7 +122,7 @@ public class CrmBusinessController { | ||
| 122 | @Operation(summary = "获得商机分页,基于指定客户") | 122 | @Operation(summary = "获得商机分页,基于指定客户") |
| 123 | public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { | 123 | public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { |
| 124 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | 124 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 125 | - PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomer(pageReqVO, getLoginUserId()); | 125 | + PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); |
| 126 | // 处理客户名称回显 | 126 | // 处理客户名称回显 |
| 127 | // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; | 127 | // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; |
| 128 | Set<Long> customerIds = pageResult.getList().stream() | 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,7 +24,4 @@ public class CrmBusinessPageReqVO extends PageParam { | ||
| 24 | @InEnum(CrmSceneTypeEnum.class) | 24 | @InEnum(CrmSceneTypeEnum.class) |
| 25 | private Integer sceneType; // 场景类型,为 null 时则表示全部 | 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,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import lombok.Data; | ||
| 6 | - | ||
| 7 | import jakarta.validation.constraints.NotNull; | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | ||
| 8 | 7 | ||
| 9 | @Schema(description = "管理后台 - 商机转移 Request VO") | 8 | @Schema(description = "管理后台 - 商机转移 Request VO") |
| 10 | @Data | 9 | @Data |
| 11 | public class CrmBusinessTransferReqVO { | 10 | public class CrmBusinessTransferReqVO { |
| 12 | 11 | ||
| 13 | @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | 12 | @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 14 | - @NotNull(message = "联系人编号不能为空") | 13 | + @NotNull(message = "商机编号不能为空") |
| 15 | private Long id; | 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,4 +88,12 @@ public class CrmClueController { | ||
| 88 | ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas); | 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,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 9 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 9 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 10 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 10 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 11 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; | 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 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 14 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 14 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 15 | import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; | 15 | import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; |
| @@ -100,7 +100,7 @@ public class CrmContactController { | @@ -100,7 +100,7 @@ public class CrmContactController { | ||
| 100 | // 3. 直属上级 | 100 | // 3. 直属上级 |
| 101 | List<CrmContactDO> parentContactList = contactService.getContactList( | 101 | List<CrmContactDO> parentContactList = contactService.getContactList( |
| 102 | Collections.singletonList(contact.getParentId()), getLoginUserId()); | 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 | @GetMapping("/simple-all-list") | 106 | @GetMapping("/simple-all-list") |
| @@ -110,7 +110,7 @@ public class CrmContactController { | @@ -110,7 +110,7 @@ public class CrmContactController { | ||
| 110 | CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); | 110 | CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); |
| 111 | pageReqVO.setPageSize(PAGE_SIZE_NONE); | 111 | pageReqVO.setPageSize(PAGE_SIZE_NONE); |
| 112 | List<CrmContactDO> list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList(); | 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 | @GetMapping("/page") | 116 | @GetMapping("/page") |
| @@ -125,7 +125,7 @@ public class CrmContactController { | @@ -125,7 +125,7 @@ public class CrmContactController { | ||
| 125 | @Operation(summary = "获得联系人分页,基于指定客户") | 125 | @Operation(summary = "获得联系人分页,基于指定客户") |
| 126 | public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { | 126 | public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { |
| 127 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); | 127 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); |
| 128 | - PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO, getLoginUserId()); | 128 | + PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO); |
| 129 | return success(convertDetailContactPage(pageResult)); | 129 | return success(convertDetailContactPage(pageResult)); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| @@ -161,7 +161,15 @@ public class CrmContactController { | @@ -161,7 +161,15 @@ public class CrmContactController { | ||
| 161 | // 3. 直属上级 | 161 | // 3. 直属上级 |
| 162 | List<CrmContactDO> parentContactList = contactService.getContactList( | 162 | List<CrmContactDO> parentContactList = contactService.getContactList( |
| 163 | convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); | 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,7 +39,4 @@ public class CrmContactPageReqVO extends PageParam { | ||
| 39 | @InEnum(CrmSceneTypeEnum.class) | 39 | @InEnum(CrmSceneTypeEnum.class) |
| 40 | private Integer sceneType; // 场景类型,为 null 时则表示全部 | 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,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 10 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; | 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 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 14 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 14 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| @@ -80,7 +80,7 @@ public class CrmContractController { | @@ -80,7 +80,7 @@ public class CrmContractController { | ||
| 80 | @PreAuthorize("@ss.hasPermission('crm:contract:query')") | 80 | @PreAuthorize("@ss.hasPermission('crm:contract:query')") |
| 81 | public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) { | 81 | public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) { |
| 82 | CrmContractDO contract = contractService.getContract(id); | 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 | @GetMapping("/page") | 86 | @GetMapping("/page") |
| @@ -95,7 +95,7 @@ public class CrmContractController { | @@ -95,7 +95,7 @@ public class CrmContractController { | ||
| 95 | @Operation(summary = "获得联系人分页,基于指定客户") | 95 | @Operation(summary = "获得联系人分页,基于指定客户") |
| 96 | public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { | 96 | public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { |
| 97 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); | 97 | Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); |
| 98 | - PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomer(pageVO, getLoginUserId()); | 98 | + PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO); |
| 99 | return success(convertDetailContractPage(pageResult)); | 99 | return success(convertDetailContractPage(pageResult)); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -108,7 +108,7 @@ public class CrmContractController { | @@ -108,7 +108,7 @@ public class CrmContractController { | ||
| 108 | PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); | 108 | PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); |
| 109 | // 导出 Excel | 109 | // 导出 Excel |
| 110 | ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class, | 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,7 +128,7 @@ public class CrmContractController { | ||
| 128 | // 2. 获取创建人、负责人列表 | 128 | // 2. 获取创建人、负责人列表 |
| 129 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, | 129 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, |
| 130 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); | 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 | @PutMapping("/transfer") | 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,7 +30,4 @@ public class CrmContractPageReqVO extends PageParam { | ||
| 30 | @InEnum(CrmSceneTypeEnum.class) | 30 | @InEnum(CrmSceneTypeEnum.class) |
| 31 | private Integer sceneType; // 场景类型,为 null 时则表示全部 | 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 | Authorization: Bearer {{token}} | 4 | Authorization: Bearer {{token}} |
| 4 | tenant-id: {{adminTenentId}} | 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,20 +11,22 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 11 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 11 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 12 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 12 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 13 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | 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 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 16 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 15 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 17 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 16 | import io.swagger.v3.oas.annotations.Operation; | 18 | import io.swagger.v3.oas.annotations.Operation; |
| 17 | import io.swagger.v3.oas.annotations.Parameter; | 19 | import io.swagger.v3.oas.annotations.Parameter; |
| 18 | import io.swagger.v3.oas.annotations.Parameters; | 20 | import io.swagger.v3.oas.annotations.Parameters; |
| 19 | import io.swagger.v3.oas.annotations.tags.Tag; | 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 | import org.mapstruct.ap.internal.util.Collections; | 25 | import org.mapstruct.ap.internal.util.Collections; |
| 21 | import org.springframework.security.access.prepost.PreAuthorize; | 26 | import org.springframework.security.access.prepost.PreAuthorize; |
| 22 | import org.springframework.validation.annotation.Validated; | 27 | import org.springframework.validation.annotation.Validated; |
| 23 | import org.springframework.web.bind.annotation.*; | 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 | import java.io.IOException; | 30 | import java.io.IOException; |
| 29 | import java.util.List; | 31 | import java.util.List; |
| 30 | import java.util.Map; | 32 | import java.util.Map; |
| @@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 36 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; | 38 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; |
| 37 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 39 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 38 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 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 | @Tag(name = "管理后台 - CRM 客户") | 43 | @Tag(name = "管理后台 - CRM 客户") |
| 41 | @RestController | 44 | @RestController |
| @@ -50,6 +53,8 @@ public class CrmCustomerController { | @@ -50,6 +53,8 @@ public class CrmCustomerController { | ||
| 50 | private DeptApi deptApi; | 53 | private DeptApi deptApi; |
| 51 | @Resource | 54 | @Resource |
| 52 | private AdminUserApi adminUserApi; | 55 | private AdminUserApi adminUserApi; |
| 56 | + @Resource | ||
| 57 | + private OperateLogApi operateLogApi; | ||
| 53 | 58 | ||
| 54 | @PostMapping("/create") | 59 | @PostMapping("/create") |
| 55 | @Operation(summary = "创建客户") | 60 | @Operation(summary = "创建客户") |
| @@ -59,7 +64,7 @@ public class CrmCustomerController { | @@ -59,7 +64,7 @@ public class CrmCustomerController { | ||
| 59 | } | 64 | } |
| 60 | 65 | ||
| 61 | @PutMapping("/update") | 66 | @PutMapping("/update") |
| 62 | - @Operation(summary = "更新客户") | 67 | + //@Operation(summary = "更新客户") |
| 63 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") | 68 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 64 | public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { | 69 | public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { |
| 65 | customerService.updateCustomer(updateReqVO); | 70 | customerService.updateCustomer(updateReqVO); |
| @@ -123,13 +128,28 @@ public class CrmCustomerController { | @@ -123,13 +128,28 @@ public class CrmCustomerController { | ||
| 123 | } | 128 | } |
| 124 | 129 | ||
| 125 | @PutMapping("/transfer") | 130 | @PutMapping("/transfer") |
| 126 | - @Operation(summary = "客户转移") | 131 | + //@Operation(summary = "客户转移") |
| 127 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") | 132 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 128 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { | 133 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { |
| 129 | customerService.transferCustomer(reqVO, getLoginUserId()); | 134 | customerService.transferCustomer(reqVO, getLoginUserId()); |
| 130 | return success(true); | 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 | // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; | 153 | // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; |
| 134 | @PutMapping("/lock") | 154 | @PutMapping("/lock") |
| 135 | @Operation(summary = "锁定/解锁客户") | 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,17 +3,20 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||
| 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; | 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | import cn.iocoder.yudao.framework.common.validation.Mobile; | 4 | import cn.iocoder.yudao.framework.common.validation.Mobile; |
| 5 | import cn.iocoder.yudao.framework.common.validation.Telephone; | 5 | import cn.iocoder.yudao.framework.common.validation.Telephone; |
| 6 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | ||
| 6 | import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; | 7 | import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; |
| 8 | +import com.mzt.logapi.starter.annotation.DiffLogField; | ||
| 7 | import io.swagger.v3.oas.annotations.media.Schema; | 9 | import io.swagger.v3.oas.annotations.media.Schema; |
| 8 | -import lombok.Data; | ||
| 9 | -import org.springframework.format.annotation.DateTimeFormat; | ||
| 10 | - | ||
| 11 | import jakarta.validation.constraints.Email; | 10 | import jakarta.validation.constraints.Email; |
| 12 | import jakarta.validation.constraints.NotEmpty; | 11 | import jakarta.validation.constraints.NotEmpty; |
| 13 | import jakarta.validation.constraints.Size; | 12 | import jakarta.validation.constraints.Size; |
| 13 | +import lombok.Data; | ||
| 14 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 15 | + | ||
| 14 | import java.time.LocalDateTime; | 16 | import java.time.LocalDateTime; |
| 15 | 17 | ||
| 16 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 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 | * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 | 22 | * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 |
| @@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | @@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||
| 23 | public class CrmCustomerBaseVO { | 26 | public class CrmCustomerBaseVO { |
| 24 | 27 | ||
| 25 | @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") | 28 | @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") |
| 29 | + @DiffLogField(name = "客户名称") | ||
| 26 | @NotEmpty(message = "客户名称不能为空") | 30 | @NotEmpty(message = "客户名称不能为空") |
| 27 | private String name; | 31 | private String name; |
| 28 | 32 | ||
| 29 | @Schema(description = "所属行业", example = "1") | 33 | @Schema(description = "所属行业", example = "1") |
| 34 | + @DiffLogField(name = "所属行业", function = "getIndustryById") | ||
| 35 | + @DictFormat(CRM_CUSTOMER_INDUSTRY) | ||
| 30 | private Integer industryId; | 36 | private Integer industryId; |
| 31 | 37 | ||
| 32 | @Schema(description = "客户等级", example = "2") | 38 | @Schema(description = "客户等级", example = "2") |
| 39 | + @DiffLogField(name = "客户等级", function = "getLevel") | ||
| 33 | @InEnum(CrmCustomerLevelEnum.class) | 40 | @InEnum(CrmCustomerLevelEnum.class) |
| 34 | private Integer level; | 41 | private Integer level; |
| 35 | 42 | ||
| 36 | @Schema(description = "客户来源", example = "3") | 43 | @Schema(description = "客户来源", example = "3") |
| 44 | + @DiffLogField(name = "客户来源", function = "getSource") | ||
| 37 | private Integer source; | 45 | private Integer source; |
| 38 | 46 | ||
| 39 | @Schema(description = "手机", example = "18000000000") | 47 | @Schema(description = "手机", example = "18000000000") |
| 48 | + @DiffLogField(name = "手机") | ||
| 40 | @Mobile | 49 | @Mobile |
| 41 | private String mobile; | 50 | private String mobile; |
| 42 | 51 | ||
| 43 | @Schema(description = "电话", example = "18000000000") | 52 | @Schema(description = "电话", example = "18000000000") |
| 53 | + @DiffLogField(name = "电话") | ||
| 44 | @Telephone | 54 | @Telephone |
| 45 | private String telephone; | 55 | private String telephone; |
| 46 | 56 | ||
| 47 | @Schema(description = "网址", example = "https://www.baidu.com") | 57 | @Schema(description = "网址", example = "https://www.baidu.com") |
| 58 | + @DiffLogField(name = "网址") | ||
| 48 | private String website; | 59 | private String website; |
| 49 | 60 | ||
| 50 | @Schema(description = "QQ", example = "123456789") | 61 | @Schema(description = "QQ", example = "123456789") |
| 62 | + @DiffLogField(name = "QQ") | ||
| 51 | @Size(max = 20, message = "QQ长度不能超过 20 个字符") | 63 | @Size(max = 20, message = "QQ长度不能超过 20 个字符") |
| 52 | private String qq; | 64 | private String qq; |
| 53 | 65 | ||
| 54 | - @Schema(description = "wechat", example = "123456789") | 66 | + @Schema(description = "微信", example = "123456789") |
| 67 | + @DiffLogField(name = "微信") | ||
| 55 | @Size(max = 255, message = "微信长度不能超过 255 个字符") | 68 | @Size(max = 255, message = "微信长度不能超过 255 个字符") |
| 56 | private String wechat; | 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 | @Email(message = "邮箱格式不正确") | 73 | @Email(message = "邮箱格式不正确") |
| 60 | @Size(max = 255, message = "邮箱长度不能超过 255 个字符") | 74 | @Size(max = 255, message = "邮箱长度不能超过 255 个字符") |
| 61 | private String email; | 75 | private String email; |
| 62 | 76 | ||
| 63 | @Schema(description = "客户描述", example = "任意文字") | 77 | @Schema(description = "客户描述", example = "任意文字") |
| 78 | + @DiffLogField(name = "客户描述") | ||
| 64 | @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") | 79 | @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") |
| 65 | private String description; | 80 | private String description; |
| 66 | 81 | ||
| 67 | @Schema(description = "备注", example = "随便") | 82 | @Schema(description = "备注", example = "随便") |
| 83 | + @DiffLogField(name = "备注") | ||
| 68 | private String remark; | 84 | private String remark; |
| 69 | 85 | ||
| 70 | @Schema(description = "地区编号", example = "20158") | 86 | @Schema(description = "地区编号", example = "20158") |
| 87 | + @DiffLogField(name = "地区编号", function = "getAreaById") | ||
| 71 | private Integer areaId; | 88 | private Integer areaId; |
| 72 | 89 | ||
| 73 | @Schema(description = "详细地址", example = "北京市海淀区") | 90 | @Schema(description = "详细地址", example = "北京市海淀区") |
| 91 | + @DiffLogField(name = "详细地址") | ||
| 74 | private String detailAddress; | 92 | private String detailAddress; |
| 75 | 93 | ||
| 76 | @Schema(description = "下次联系时间") | 94 | @Schema(description = "下次联系时间") |
| 95 | + @DiffLogField(name = "下次联系时间") | ||
| 77 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 96 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 78 | private LocalDateTime contactNextTime; | 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,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 3 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import lombok.Data; | ||
| 6 | - | ||
| 7 | import jakarta.validation.constraints.NotNull; | 5 | import jakarta.validation.constraints.NotNull; |
| 6 | +import lombok.Data; | ||
| 8 | 7 | ||
| 9 | @Schema(description = "管理后台 - CRM 客户转移 Request VO") | 8 | @Schema(description = "管理后台 - CRM 客户转移 Request VO") |
| 10 | @Data | 9 | @Data |
| 11 | public class CrmCustomerTransferReqVO { | 10 | public class CrmCustomerTransferReqVO { |
| 12 | 11 | ||
| 13 | @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | 12 | @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 14 | - @NotNull(message = "联系人编号不能为空") | 13 | + @NotNull(message = "客户编号不能为空") |
| 15 | private Long id; | 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,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | 7 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 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 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; |
| 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| @@ -36,6 +33,7 @@ import java.util.Map; | @@ -36,6 +33,7 @@ import java.util.Map; | ||
| 36 | import java.util.stream.Stream; | 33 | import java.util.stream.Stream; |
| 37 | 34 | ||
| 38 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 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 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | 37 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; |
| 40 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 38 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 41 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 39 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| @@ -94,7 +92,7 @@ public class CrmReceivableController { | @@ -94,7 +92,7 @@ public class CrmReceivableController { | ||
| 94 | @Operation(summary = "获得回款分页") | 92 | @Operation(summary = "获得回款分页") |
| 95 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") | 93 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") |
| 96 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { | 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 | return success(convertDetailReceivablePage(pageResult)); | 96 | return success(convertDetailReceivablePage(pageResult)); |
| 99 | } | 97 | } |
| 100 | 98 | ||
| @@ -102,7 +100,7 @@ public class CrmReceivableController { | @@ -102,7 +100,7 @@ public class CrmReceivableController { | ||
| 102 | @Operation(summary = "获得回款分页,基于指定客户") | 100 | @Operation(summary = "获得回款分页,基于指定客户") |
| 103 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { | 101 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { |
| 104 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | 102 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 105 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomer(pageReqVO); | 103 | + PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); |
| 106 | return success(convertDetailReceivablePage(pageResult)); | 104 | return success(convertDetailReceivablePage(pageResult)); |
| 107 | } | 105 | } |
| 108 | 106 | ||
| @@ -113,7 +111,8 @@ public class CrmReceivableController { | @@ -113,7 +111,8 @@ public class CrmReceivableController { | ||
| 113 | @OperateLog(type = EXPORT) | 111 | @OperateLog(type = EXPORT) |
| 114 | public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, | 112 | public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, |
| 115 | HttpServletResponse response) throws IOException { | 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 | // 导出 Excel | 116 | // 导出 Excel |
| 118 | ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, | 117 | ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, |
| 119 | convertDetailReceivablePage(pageResult).getList()); | 118 | convertDetailReceivablePage(pageResult).getList()); |
| @@ -142,4 +141,12 @@ public class CrmReceivableController { | @@ -142,4 +141,12 @@ public class CrmReceivableController { | ||
| 142 | return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); | 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,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | 7 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 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 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; |
| 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| @@ -38,6 +35,7 @@ import java.util.Map; | @@ -38,6 +35,7 @@ import java.util.Map; | ||
| 38 | import java.util.stream.Stream; | 35 | import java.util.stream.Stream; |
| 39 | 36 | ||
| 40 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 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 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | 39 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; |
| 42 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 40 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 43 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 41 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| @@ -65,7 +63,7 @@ public class CrmReceivablePlanController { | @@ -65,7 +63,7 @@ public class CrmReceivablePlanController { | ||
| 65 | @Operation(summary = "创建回款计划") | 63 | @Operation(summary = "创建回款计划") |
| 66 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") | 64 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") |
| 67 | public CommonResult<Long> createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) { | 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 | @PutMapping("/update") | 69 | @PutMapping("/update") |
| @@ -98,7 +96,7 @@ public class CrmReceivablePlanController { | @@ -98,7 +96,7 @@ public class CrmReceivablePlanController { | ||
| 98 | @Operation(summary = "获得回款计划分页") | 96 | @Operation(summary = "获得回款计划分页") |
| 99 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | 97 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 100 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | 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 | return success(convertDetailReceivablePlanPage(pageResult)); | 100 | return success(convertDetailReceivablePlanPage(pageResult)); |
| 103 | } | 101 | } |
| 104 | 102 | ||
| @@ -106,7 +104,7 @@ public class CrmReceivablePlanController { | @@ -106,7 +104,7 @@ public class CrmReceivablePlanController { | ||
| 106 | @Operation(summary = "获得回款计划分页,基于指定客户") | 104 | @Operation(summary = "获得回款计划分页,基于指定客户") |
| 107 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | 105 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 108 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | 106 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 109 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomer(pageReqVO); | 107 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); |
| 110 | return success(convertDetailReceivablePlanPage(pageResult)); | 108 | return success(convertDetailReceivablePlanPage(pageResult)); |
| 111 | } | 109 | } |
| 112 | 110 | ||
| @@ -117,7 +115,8 @@ public class CrmReceivablePlanController { | @@ -117,7 +115,8 @@ public class CrmReceivablePlanController { | ||
| 117 | @OperateLog(type = EXPORT) | 115 | @OperateLog(type = EXPORT) |
| 118 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, | 116 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, |
| 119 | HttpServletResponse response) throws IOException { | 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 | // 导出 Excel | 120 | // 导出 Excel |
| 122 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, | 121 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, |
| 123 | convertDetailReceivablePlanPage(pageResult).getList()); | 122 | convertDetailReceivablePlanPage(pageResult).getList()); |
| @@ -149,4 +148,12 @@ public class CrmReceivablePlanController { | @@ -149,4 +148,12 @@ public class CrmReceivablePlanController { | ||
| 149 | return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); | 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,7 +25,4 @@ public class CrmReceivablePlanPageReqVO extends PageParam { | ||
| 25 | @InEnum(CrmSceneTypeEnum.class) | 25 | @InEnum(CrmSceneTypeEnum.class) |
| 26 | private Integer sceneType; // 场景类型,为 null 时则表示全部 | 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,7 +27,4 @@ public class CrmReceivablePageReqVO extends PageParam { | ||
| 27 | @InEnum(CrmSceneTypeEnum.class) | 27 | @InEnum(CrmSceneTypeEnum.class) |
| 28 | private Integer sceneType; // 场景类型,为 null 时则表示全部 | 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 | package cn.iocoder.yudao.module.crm.convert.clue; | 1 | package cn.iocoder.yudao.module.crm.convert.clue; |
| 2 | 2 | ||
| 3 | -import java.util.*; | ||
| 4 | - | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | - | ||
| 7 | -import org.mapstruct.Mapper; | ||
| 8 | -import org.mapstruct.factory.Mappers; | ||
| 9 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | 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 | * 线索 Convert | 14 | * 线索 Convert |
| @@ -29,4 +30,7 @@ public interface CrmClueConvert { | @@ -29,4 +30,7 @@ public interface CrmClueConvert { | ||
| 29 | 30 | ||
| 30 | List<CrmClueExcelVO> convertList02(List<CrmClueDO> list); | 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,7 +9,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe | ||
| 9 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 9 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 10 | import org.mapstruct.Mapper; | 10 | import org.mapstruct.Mapper; |
| 11 | import org.mapstruct.Mapping; | 11 | import org.mapstruct.Mapping; |
| 12 | -import org.mapstruct.Mappings; | ||
| 13 | import org.mapstruct.factory.Mappers; | 12 | import org.mapstruct.factory.Mappers; |
| 14 | 13 | ||
| 15 | import java.util.List; | 14 | import java.util.List; |
| @@ -26,9 +25,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd | @@ -26,9 +25,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd | ||
| 26 | * @author 芋道源码 | 25 | * @author 芋道源码 |
| 27 | */ | 26 | */ |
| 28 | @Mapper | 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 | CrmContactDO convert(CrmContactCreateReqVO bean); | 32 | CrmContactDO convert(CrmContactCreateReqVO bean); |
| 34 | 33 | ||
| @@ -48,10 +47,7 @@ public interface ContactConvert { | @@ -48,10 +47,7 @@ public interface ContactConvert { | ||
| 48 | 47 | ||
| 49 | List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list); | 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 | CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); | 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,7 +8,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe | ||
| 8 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 8 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 9 | import org.mapstruct.Mapper; | 9 | import org.mapstruct.Mapper; |
| 10 | import org.mapstruct.Mapping; | 10 | import org.mapstruct.Mapping; |
| 11 | -import org.mapstruct.Mappings; | ||
| 12 | import org.mapstruct.factory.Mappers; | 11 | import org.mapstruct.factory.Mappers; |
| 13 | 12 | ||
| 14 | import java.util.List; | 13 | import java.util.List; |
| @@ -23,9 +22,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd | @@ -23,9 +22,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd | ||
| 23 | * @author dhb52 | 22 | * @author dhb52 |
| 24 | */ | 23 | */ |
| 25 | @Mapper | 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 | CrmContractDO convert(CrmContractCreateReqVO bean); | 29 | CrmContractDO convert(CrmContractCreateReqVO bean); |
| 31 | 30 | ||
| @@ -39,10 +38,7 @@ public interface ContractConvert { | @@ -39,10 +38,7 @@ public interface ContractConvert { | ||
| 39 | 38 | ||
| 40 | List<CrmContractExcelVO> convertList02(List<CrmContractDO> list); | 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 | CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); | 42 | CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); |
| 47 | 43 | ||
| 48 | default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap, | 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,12 +3,15 @@ package cn.iocoder.yudao.module.crm.convert.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 11 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | ||
| 10 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 12 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 11 | import org.mapstruct.Mapper; | 13 | import org.mapstruct.Mapper; |
| 14 | +import org.mapstruct.Mapping; | ||
| 12 | import org.mapstruct.factory.Mappers; | 15 | import org.mapstruct.factory.Mappers; |
| 13 | 16 | ||
| 14 | import java.util.List; | 17 | import java.util.List; |
| @@ -58,4 +61,7 @@ public interface CrmReceivableConvert { | @@ -58,4 +61,7 @@ public interface CrmReceivableConvert { | ||
| 58 | findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); | 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,13 +3,16 @@ package cn.iocoder.yudao.module.crm.convert.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 12 | +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | ||
| 11 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 13 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 12 | import org.mapstruct.Mapper; | 14 | import org.mapstruct.Mapper; |
| 15 | +import org.mapstruct.Mapping; | ||
| 13 | import org.mapstruct.factory.Mappers; | 16 | import org.mapstruct.factory.Mappers; |
| 14 | 17 | ||
| 15 | import java.util.List; | 18 | import java.util.List; |
| @@ -63,4 +66,7 @@ public interface CrmReceivablePlanConvert { | @@ -63,4 +66,7 @@ public interface CrmReceivablePlanConvert { | ||
| 63 | findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); | 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; |
| @@ -27,14 +28,23 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | @@ -27,14 +28,23 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | ||
| 27 | .set(CrmBusinessDO::getOwnerUserId, ownerUserId)); | 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 | default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { | 38 | default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); | 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 | query.selectAll(CrmBusinessDO.class) | 47 | query.selectAll(CrmBusinessDO.class) |
| 37 | - .eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 | ||
| 38 | .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) | 48 | .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) |
| 39 | .orderByDesc(CrmBusinessDO::getId); | 49 | .orderByDesc(CrmBusinessDO::getId); |
| 40 | return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); | 50 | return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); |
| @@ -43,7 +53,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | @@ -43,7 +53,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | ||
| 43 | default List<CrmBusinessDO> selectBatchIds(Collection<Long> ids, Long userId) { | 53 | default List<CrmBusinessDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 44 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); | 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 | return selectJoinList(CrmBusinessDO.class, query); | 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,8 +30,11 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | ||
| 30 | default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { | 30 | default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); | 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 | query.selectAll(CrmClueDO.class) | 39 | query.selectAll(CrmClueDO.class) |
| 37 | .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) | 40 | .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) |
| @@ -44,7 +47,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | @@ -44,7 +47,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | ||
| 44 | default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) { | 47 | default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 45 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); | 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 | return selectJoinList(CrmClueDO.class, query); | 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contact; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| @@ -27,14 +28,28 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | @@ -27,14 +28,28 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | ||
| 27 | .set(CrmContactDO::getOwnerUserId, ownerUserId)); | 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 | default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { | 43 | default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); | 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 | query.selectAll(CrmContactDO.class) | 52 | query.selectAll(CrmContactDO.class) |
| 37 | - .eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 | ||
| 38 | .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) | 53 | .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) |
| 39 | .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) | 54 | .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) |
| 40 | .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) | 55 | .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) |
| @@ -48,7 +63,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | @@ -48,7 +63,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | ||
| 48 | default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long userId) { | 63 | default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 49 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); | 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 | return selectJoinList(CrmContactDO.class, query); | 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| @@ -27,13 +28,26 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | @@ -27,13 +28,26 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | ||
| 27 | .set(CrmContractDO::getOwnerUserId, ownerUserId)); | 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 | default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { | 41 | default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); | 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 | mpjLambdaWrapperX.selectAll(CrmContractDO.class) | 50 | mpjLambdaWrapperX.selectAll(CrmContractDO.class) |
| 36 | - .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) | ||
| 37 | .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) | 51 | .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) |
| 38 | .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) | 52 | .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) |
| 39 | .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) | 53 | .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) |
| @@ -45,7 +59,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | @@ -45,7 +59,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | ||
| 45 | default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) { | 59 | default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 46 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); | 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 | return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); | 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,8 +30,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||
| 30 | default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | 30 | default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | 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 | query.selectAll(CrmCustomerDO.class) | 39 | query.selectAll(CrmCustomerDO.class) |
| 37 | .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) | 40 | .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) |
| @@ -45,7 +48,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | @@ -45,7 +48,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||
| 45 | default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) { | 48 | default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) { |
| 46 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | 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 | return selectJoinList(CrmCustomerDO.class, query); | 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,4 +46,10 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> { | ||
| 46 | .eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId)); | 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,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 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 | import org.apache.ibatis.annotations.Mapper; | 12 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 13 | ||
| 14 | +import java.util.Collection; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 10 | /** | 17 | /** |
| 11 | * 回款 Mapper | 18 | * 回款 Mapper |
| 12 | * | 19 | * |
| @@ -15,15 +22,13 @@ import org.apache.ibatis.annotations.Mapper; | @@ -15,15 +22,13 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 15 | @Mapper | 22 | @Mapper |
| 16 | public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | 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 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() | 32 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() |
| 28 | .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 | 33 | .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 |
| 29 | .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) | 34 | .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) |
| @@ -31,4 +36,27 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | @@ -31,4 +36,27 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | ||
| 31 | .orderByDesc(CrmReceivableDO::getId)); | 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,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 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 | import org.apache.ibatis.annotations.Mapper; | 12 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 13 | ||
| 14 | +import java.util.Collection; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 10 | /** | 17 | /** |
| 11 | * 回款计划 Mapper | 18 | * 回款计划 Mapper |
| 12 | * | 19 | * |
| @@ -15,18 +22,40 @@ import org.apache.ibatis.annotations.Mapper; | @@ -15,18 +22,40 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 15 | @Mapper | 22 | @Mapper |
| 16 | public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> { | 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 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>() | 32 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>() |
| 27 | .eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 | 33 | .eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 |
| 28 | .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) | 34 | .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) |
| 29 | .orderByDesc(CrmReceivablePlanDO::getId)); | 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,10 +75,9 @@ public interface CrmBusinessService { | ||
| 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 | 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 |
| 76 | * | 76 | * |
| 77 | * @param pageReqVO 分页查询 | 77 | * @param pageReqVO 分页查询 |
| 78 | - * @param userId 用户编号 | ||
| 79 | * @return 联系人分页 | 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,11 +111,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { | ||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | @Override | 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 | @Override | 119 | @Override |
| @@ -127,7 +125,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { | @@ -127,7 +125,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { | ||
| 127 | // 2.1 数据权限转移 | 125 | // 2.1 数据权限转移 |
| 128 | crmPermissionService.transferPermission( | 126 | crmPermissionService.transferPermission( |
| 129 | CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); | 127 | CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); |
| 130 | - | ||
| 131 | // 2.2 设置新的负责人 | 128 | // 2.2 设置新的负责人 |
| 132 | businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | 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,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.clue; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 8 | import jakarta.validation.Valid; | 9 | import jakarta.validation.Valid; |
| @@ -64,4 +65,12 @@ public interface CrmClueService { | @@ -64,4 +65,12 @@ public interface CrmClueService { | ||
| 64 | */ | 65 | */ |
| 65 | PageResult<CrmClueDO> getCluePage(CrmCluePageReqVO pageReqVO, Long userId); | 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,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; | 6 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | 9 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; |
| 9 | import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; | 10 | import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| @@ -101,4 +102,18 @@ public class CrmClueServiceImpl implements CrmClueService { | @@ -101,4 +102,18 @@ public class CrmClueServiceImpl implements CrmClueService { | ||
| 101 | return clueMapper.selectPage(pageReqVO, userId); | 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,8 +3,10 @@ package cn.iocoder.yudao.module.crm.service.contact; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 9 | +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 8 | import jakarta.validation.Valid; | 10 | import jakarta.validation.Valid; |
| 9 | 11 | ||
| 10 | import java.util.Collection; | 12 | import java.util.Collection; |
| @@ -71,12 +73,19 @@ public interface CrmContactService { | @@ -71,12 +73,19 @@ public interface CrmContactService { | ||
| 71 | /** | 73 | /** |
| 72 | * 获得联系人分页 | 74 | * 获得联系人分页 |
| 73 | * | 75 | * |
| 74 | - * 数据权限:基于 {@link CrmContactDO} | 76 | + * 数据权限:基于 {@link CrmCustomerDO} |
| 75 | * | 77 | * |
| 76 | * @param pageVO 分页查询 | 78 | * @param pageVO 分页查询 |
| 77 | - * @param userId 用户编号 | ||
| 78 | * @return 联系人分页 | 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,11 +3,8 @@ package cn.iocoder.yudao.module.crm.service.contact; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.ListUtil; | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 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 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 10 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| @@ -56,7 +53,7 @@ public class CrmContactServiceImpl implements CrmContactService { | @@ -56,7 +53,7 @@ public class CrmContactServiceImpl implements CrmContactService { | ||
| 56 | // 1.1 校验 | 53 | // 1.1 校验 |
| 57 | validateRelationDataExists(createReqVO); | 54 | validateRelationDataExists(createReqVO); |
| 58 | // 1.2 插入 | 55 | // 1.2 插入 |
| 59 | - CrmContactDO contact = ContactConvert.INSTANCE.convert(createReqVO); | 56 | + CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); |
| 60 | contactMapper.insert(contact); | 57 | contactMapper.insert(contact); |
| 61 | 58 | ||
| 62 | // 2. 创建数据权限 | 59 | // 2. 创建数据权限 |
| @@ -73,7 +70,7 @@ public class CrmContactServiceImpl implements CrmContactService { | @@ -73,7 +70,7 @@ public class CrmContactServiceImpl implements CrmContactService { | ||
| 73 | validateContactExists(updateReqVO.getId()); | 70 | validateContactExists(updateReqVO.getId()); |
| 74 | validateRelationDataExists(updateReqVO); | 71 | validateRelationDataExists(updateReqVO); |
| 75 | // 2. 更新 | 72 | // 2. 更新 |
| 76 | - CrmContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO); | 73 | + CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); |
| 77 | contactMapper.updateById(updateObj); | 74 | contactMapper.updateById(updateObj); |
| 78 | } | 75 | } |
| 79 | 76 | ||
| @@ -134,11 +131,23 @@ public class CrmContactServiceImpl implements CrmContactService { | @@ -134,11 +131,23 @@ public class CrmContactServiceImpl implements CrmContactService { | ||
| 134 | } | 131 | } |
| 135 | 132 | ||
| 136 | @Override | 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,12 +75,9 @@ public interface CrmContractService { | ||
| 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 | 75 | * 数据权限:基于 {@link CrmCustomerDO} 读取 |
| 76 | * | 76 | * |
| 77 | * @param pageReqVO 分页查询 | 77 | * @param pageReqVO 分页查询 |
| 78 | - * @param userId 用户编号 | ||
| 79 | * @return 联系人分页 | 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 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreat | ||
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; |
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; | 8 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; |
| 9 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; | 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 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; | 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| @@ -44,7 +44,7 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -44,7 +44,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 44 | @Override | 44 | @Override |
| 45 | public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) { | 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 | contractMapper.insert(contract); | 48 | contractMapper.insert(contract); |
| 49 | 49 | ||
| 50 | // 创建数据权限 | 50 | // 创建数据权限 |
| @@ -61,7 +61,7 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -61,7 +61,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 61 | // 校验存在 | 61 | // 校验存在 |
| 62 | validateContractExists(updateReqVO.getId()); | 62 | validateContractExists(updateReqVO.getId()); |
| 63 | // 更新 | 63 | // 更新 |
| 64 | - CrmContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO); | 64 | + CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO); |
| 65 | contractMapper.updateById(updateObj); | 65 | contractMapper.updateById(updateObj); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| @@ -105,6 +105,12 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -105,6 +105,12 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | @Override | 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 | @Transactional(rollbackFor = Exception.class) | 114 | @Transactional(rollbackFor = Exception.class) |
| 109 | public void transferContract(CrmContractTransferReqVO reqVO, Long userId) { | 115 | public void transferContract(CrmContractTransferReqVO reqVO, Long userId) { |
| 110 | // 1. 校验合同是否存在 | 116 | // 1. 校验合同是否存在 |
| @@ -112,7 +118,7 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -112,7 +118,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 112 | 118 | ||
| 113 | // 2.1 数据权限转移 | 119 | // 2.1 数据权限转移 |
| 114 | crmPermissionService.transferPermission( | 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 | // 2.2 设置负责人 | 122 | // 2.2 设置负责人 |
| 117 | contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.customer; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; | 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | 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,6 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | ||
| 15 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 16 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 17 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 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 | import jakarta.annotation.Resource; | 22 | import jakarta.annotation.Resource; |
| 19 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
| 20 | import org.springframework.transaction.annotation.Transactional; | 24 | import org.springframework.transaction.annotation.Transactional; |
| @@ -24,6 +28,8 @@ import java.util.*; | @@ -24,6 +28,8 @@ import java.util.*; | ||
| 24 | 28 | ||
| 25 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | 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 | import static java.util.Collections.singletonList; | 33 | import static java.util.Collections.singletonList; |
| 28 | 34 | ||
| 29 | /** | 35 | /** |
| @@ -59,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -59,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 59 | 65 | ||
| 60 | @Override | 66 | @Override |
| 61 | @Transactional(rollbackFor = Exception.class) | 67 | @Transactional(rollbackFor = Exception.class) |
| 68 | + @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") | ||
| 62 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | 69 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 63 | public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | 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 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); | 77 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); |
| 69 | customerMapper.updateById(updateObj); | 78 | customerMapper.updateById(updateObj); |
| @@ -82,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -82,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 82 | crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); | 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 | throw exception(CUSTOMER_NOT_EXISTS); | 97 | throw exception(CUSTOMER_NOT_EXISTS); |
| 88 | } | 98 | } |
| 99 | + return customerDO; | ||
| 89 | } | 100 | } |
| 90 | 101 | ||
| 91 | @Override | 102 | @Override |
| @@ -114,7 +125,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -114,7 +125,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 114 | */ | 125 | */ |
| 115 | @Override | 126 | @Override |
| 116 | public void validateCustomer(Long customerId) { | 127 | public void validateCustomer(Long customerId) { |
| 117 | - // TODO puhui999: 不返回客户不走校验应该可行 | ||
| 118 | // 校验客户是否存在 | 128 | // 校验客户是否存在 |
| 119 | if (customerId == null) { | 129 | if (customerId == null) { |
| 120 | throw exception(CUSTOMER_NOT_EXISTS); | 130 | throw exception(CUSTOMER_NOT_EXISTS); |
| @@ -127,11 +137,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -127,11 +137,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 127 | 137 | ||
| 128 | @Override | 138 | @Override |
| 129 | @Transactional(rollbackFor = Exception.class) | 139 | @Transactional(rollbackFor = Exception.class) |
| 140 | + @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") | ||
| 130 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) | 141 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) |
| 131 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { | 142 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { |
| 132 | // 1. 校验客户是否存在 | 143 | // 1. 校验客户是否存在 |
| 133 | validateCustomer(reqVO.getId()); | 144 | validateCustomer(reqVO.getId()); |
| 134 | - | 145 | + // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 |
| 146 | + LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); | ||
| 135 | // 2.1 数据权限转移 | 147 | // 2.1 数据权限转移 |
| 136 | crmPermissionService.transferPermission( | 148 | crmPermissionService.transferPermission( |
| 137 | CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); | 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,15 +138,13 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | ||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | @Override | 140 | @Override |
| 141 | + @Transactional(rollbackFor = Exception.class) | ||
| 141 | public void deletePermission(Integer bizType, Long bizId) { | 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 | @Override | 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,11 +3,12 @@ package cn.iocoder.yudao.module.crm.service.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 9 | - | ||
| 10 | import jakarta.validation.Valid; | 10 | import jakarta.validation.Valid; |
| 11 | + | ||
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 13 | 14 | ||
| @@ -24,7 +25,7 @@ public interface CrmReceivablePlanService { | @@ -24,7 +25,7 @@ public interface CrmReceivablePlanService { | ||
| 24 | * @param createReqVO 创建信息 | 25 | * @param createReqVO 创建信息 |
| 25 | * @return 编号 | 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,9 +63,10 @@ public interface CrmReceivablePlanService { | ||
| 62 | * 数据权限:基于 {@link CrmReceivablePlanDO} 读取 | 63 | * 数据权限:基于 {@link CrmReceivablePlanDO} 读取 |
| 63 | * | 64 | * |
| 64 | * @param pageReqVO 分页查询 | 65 | * @param pageReqVO 分页查询 |
| 66 | + * @param userId 用户编号 | ||
| 65 | * @return 回款计划分页 | 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,6 +76,14 @@ public interface CrmReceivablePlanService { | ||
| 74 | * @param pageReqVO 分页查询 | 76 | * @param pageReqVO 分页查询 |
| 75 | * @return 回款计划分页 | 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 +6,7 @@ import cn.hutool.core.util.ObjectUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; |
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; | 10 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 10 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; | 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; |
| 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 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,10 +18,12 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||
| 17 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 18 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; |
| 18 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 19 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 19 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 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 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 21 | import org.springframework.validation.annotation.Validated; | 25 | import org.springframework.validation.annotation.Validated; |
| 22 | 26 | ||
| 23 | -import jakarta.annotation.Resource; | ||
| 24 | import java.util.Collection; | 27 | import java.util.Collection; |
| 25 | import java.util.List; | 28 | import java.util.List; |
| 26 | 29 | ||
| @@ -28,7 +31,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | @@ -28,7 +31,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | ||
| 28 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | 31 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 29 | 32 | ||
| 30 | // TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈; | 33 | // TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈; |
| 31 | -// TODO @puhui999:数据权限 | 34 | + |
| 32 | /** | 35 | /** |
| 33 | * 回款计划 Service 实现类 | 36 | * 回款计划 Service 实现类 |
| 34 | * | 37 | * |
| @@ -45,9 +48,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -45,9 +48,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 45 | private CrmContractService contractService; | 48 | private CrmContractService contractService; |
| 46 | @Resource | 49 | @Resource |
| 47 | private CrmCustomerService customerService; | 50 | private CrmCustomerService customerService; |
| 51 | + @Resource | ||
| 52 | + private CrmPermissionService crmPermissionService; | ||
| 48 | 53 | ||
| 49 | @Override | 54 | @Override |
| 50 | - public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO) { | 55 | + public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) { |
| 51 | // 插入 | 56 | // 插入 |
| 52 | CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); | 57 | CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); |
| 53 | receivablePlan.setFinishStatus(false); | 58 | receivablePlan.setFinishStatus(false); |
| @@ -55,29 +60,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -55,29 +60,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 55 | checkReceivablePlan(receivablePlan); | 60 | checkReceivablePlan(receivablePlan); |
| 56 | 61 | ||
| 57 | receivablePlanMapper.insert(receivablePlan); | 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 | return receivablePlan.getId(); | 67 | return receivablePlan.getId(); |
| 60 | } | 68 | } |
| 61 | 69 | ||
| 62 | private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) { | 70 | private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) { |
| 63 | 71 | ||
| 64 | - if(ObjectUtil.isNull(receivablePlan.getContractId())){ | 72 | + if (ObjectUtil.isNull(receivablePlan.getContractId())) { |
| 65 | throw exception(CONTRACT_NOT_EXISTS); | 73 | throw exception(CONTRACT_NOT_EXISTS); |
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | CrmContractDO contract = contractService.getContract(receivablePlan.getContractId()); | 76 | CrmContractDO contract = contractService.getContract(receivablePlan.getContractId()); |
| 69 | - if(ObjectUtil.isNull(contract)){ | 77 | + if (ObjectUtil.isNull(contract)) { |
| 70 | throw exception(CONTRACT_NOT_EXISTS); | 78 | throw exception(CONTRACT_NOT_EXISTS); |
| 71 | } | 79 | } |
| 72 | 80 | ||
| 73 | CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId()); | 81 | CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId()); |
| 74 | - if(ObjectUtil.isNull(customer)){ | 82 | + if (ObjectUtil.isNull(customer)) { |
| 75 | throw exception(CUSTOMER_NOT_EXISTS); | 83 | throw exception(CUSTOMER_NOT_EXISTS); |
| 76 | } | 84 | } |
| 77 | 85 | ||
| 78 | } | 86 | } |
| 79 | 87 | ||
| 80 | @Override | 88 | @Override |
| 89 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | ||
| 81 | public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { | 90 | public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { |
| 82 | // 校验存在 | 91 | // 校验存在 |
| 83 | validateReceivablePlanExists(updateReqVO.getId()); | 92 | validateReceivablePlanExists(updateReqVO.getId()); |
| @@ -88,6 +97,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -88,6 +97,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 88 | } | 97 | } |
| 89 | 98 | ||
| 90 | @Override | 99 | @Override |
| 100 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | ||
| 91 | public void deleteReceivablePlan(Long id) { | 101 | public void deleteReceivablePlan(Long id) { |
| 92 | // 校验存在 | 102 | // 校验存在 |
| 93 | validateReceivablePlanExists(id); | 103 | validateReceivablePlanExists(id); |
| @@ -102,6 +112,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -102,6 +112,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 102 | } | 112 | } |
| 103 | 113 | ||
| 104 | @Override | 114 | @Override |
| 115 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.READ) | ||
| 105 | public CrmReceivablePlanDO getReceivablePlan(Long id) { | 116 | public CrmReceivablePlanDO getReceivablePlan(Long id) { |
| 106 | return receivablePlanMapper.selectById(id); | 117 | return receivablePlanMapper.selectById(id); |
| 107 | } | 118 | } |
| @@ -115,14 +126,28 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -115,14 +126,28 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 115 | } | 126 | } |
| 116 | 127 | ||
| 117 | @Override | 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 | @Override | 133 | @Override |
| 123 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) | 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,11 +3,12 @@ package cn.iocoder.yudao.module.crm.service.receivable; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; | 4 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 9 | - | ||
| 10 | import jakarta.validation.Valid; | 10 | import jakarta.validation.Valid; |
| 11 | + | ||
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 13 | 14 | ||
| @@ -62,9 +63,10 @@ public interface CrmReceivableService { | @@ -62,9 +63,10 @@ public interface CrmReceivableService { | ||
| 62 | * 数据权限:基于 {@link CrmReceivableDO} 读取 | 63 | * 数据权限:基于 {@link CrmReceivableDO} 读取 |
| 63 | * | 64 | * |
| 64 | * @param pageReqVO 分页查询 | 65 | * @param pageReqVO 分页查询 |
| 66 | + * @param userId 用户编号 | ||
| 65 | * @return 回款分页 | 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,6 +76,14 @@ public interface CrmReceivableService { | ||
| 74 | * @param pageReqVO 分页查询 | 76 | * @param pageReqVO 分页查询 |
| 75 | * @return 回款分页 | 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,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; | 8 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; |
| 9 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; | 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 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; | 11 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 11 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; | 12 | import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; |
| 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 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,10 +21,11 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||
| 20 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 21 | import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; |
| 21 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 22 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 22 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 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 | import org.springframework.stereotype.Service; | 26 | import org.springframework.stereotype.Service; |
| 24 | import org.springframework.validation.annotation.Validated; | 27 | import org.springframework.validation.annotation.Validated; |
| 25 | 28 | ||
| 26 | -import jakarta.annotation.Resource; | ||
| 27 | import java.util.Collection; | 29 | import java.util.Collection; |
| 28 | import java.util.List; | 30 | import java.util.List; |
| 29 | 31 | ||
| @@ -48,6 +50,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -48,6 +50,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 48 | private CrmCustomerService customerService; | 50 | private CrmCustomerService customerService; |
| 49 | @Resource | 51 | @Resource |
| 50 | private CrmReceivablePlanService receivablePlanService; | 52 | private CrmReceivablePlanService receivablePlanService; |
| 53 | + @Resource | ||
| 54 | + private CrmPermissionService crmPermissionService; | ||
| 51 | 55 | ||
| 52 | // TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan? | 56 | // TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan? |
| 53 | @Override | 57 | @Override |
| @@ -70,22 +74,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -70,22 +74,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 70 | // TODO @liuhongfeng:这里的括号要注意排版; | 74 | // TODO @liuhongfeng:这里的括号要注意排版; |
| 71 | private void checkReceivable(CrmReceivableDO receivable) { | 75 | private void checkReceivable(CrmReceivableDO receivable) { |
| 72 | // TODO @liuhongfeng:这个放在参数校验合适 | 76 | // TODO @liuhongfeng:这个放在参数校验合适 |
| 73 | - if(ObjectUtil.isNull(receivable.getContractId())){ | 77 | + if (ObjectUtil.isNull(receivable.getContractId())) { |
| 74 | throw exception(CONTRACT_NOT_EXISTS); | 78 | throw exception(CONTRACT_NOT_EXISTS); |
| 75 | } | 79 | } |
| 76 | 80 | ||
| 77 | CrmContractDO contract = contractService.getContract(receivable.getContractId()); | 81 | CrmContractDO contract = contractService.getContract(receivable.getContractId()); |
| 78 | - if(ObjectUtil.isNull(contract)){ | 82 | + if (ObjectUtil.isNull(contract)) { |
| 79 | throw exception(CONTRACT_NOT_EXISTS); | 83 | throw exception(CONTRACT_NOT_EXISTS); |
| 80 | } | 84 | } |
| 81 | 85 | ||
| 82 | CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId()); | 86 | CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId()); |
| 83 | - if(ObjectUtil.isNull(customer)){ | 87 | + if (ObjectUtil.isNull(customer)) { |
| 84 | throw exception(CUSTOMER_NOT_EXISTS); | 88 | throw exception(CUSTOMER_NOT_EXISTS); |
| 85 | } | 89 | } |
| 86 | 90 | ||
| 87 | CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId()); | 91 | CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId()); |
| 88 | - if(ObjectUtil.isNull(receivablePlan)){ | 92 | + if (ObjectUtil.isNull(receivablePlan)) { |
| 89 | throw exception(RECEIVABLE_PLAN_NOT_EXISTS); | 93 | throw exception(RECEIVABLE_PLAN_NOT_EXISTS); |
| 90 | } | 94 | } |
| 91 | 95 | ||
| @@ -129,16 +133,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -129,16 +133,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 129 | return receivableMapper.selectBatchIds(ids); | 133 | return receivableMapper.selectBatchIds(ids); |
| 130 | } | 134 | } |
| 131 | 135 | ||
| 132 | - // TODO @芋艿:数据权限 | ||
| 133 | @Override | 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 | @Override | 141 | @Override |
| 139 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) | 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 +6,7 @@ import cn.hutool.extra.spring.SpringUtil; | ||
| 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; |
| 7 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 7 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 8 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | 8 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; |
| 9 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||
| 9 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 10 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 10 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 11 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 11 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; | 12 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| @@ -17,7 +18,7 @@ import java.util.List; | @@ -17,7 +18,7 @@ import java.util.List; | ||
| 17 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 18 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 20 | - * CRM 分页查询工具类 | 21 | + * CRM 查询工具类 |
| 21 | * | 22 | * |
| 22 | * @author HUIHUI | 23 | * @author HUIHUI |
| 23 | */ | 24 | */ |
| @@ -26,17 +27,17 @@ public class CrmQueryWrapperUtils { | @@ -26,17 +27,17 @@ public class CrmQueryWrapperUtils { | ||
| 26 | /** | 27 | /** |
| 27 | * 构造 CRM 数据类型数据分页查询条件 | 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 | // 1. 构建数据权限连表条件 | 41 | // 1. 构建数据权限连表条件 |
| 41 | if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 | 42 | if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 |
| 42 | query.innerJoin(CrmPermissionDO.class, on -> | 43 | query.innerJoin(CrmPermissionDO.class, on -> |
| @@ -48,52 +49,55 @@ public class CrmQueryWrapperUtils { | @@ -48,52 +49,55 @@ public class CrmQueryWrapperUtils { | ||
| 48 | query.eq("owner_user_id", userId); | 49 | query.eq("owner_user_id", userId); |
| 49 | } | 50 | } |
| 50 | // 2.2 场景二:我参与的数据 | 51 | // 2.2 场景二:我参与的数据 |
| 51 | - // TODO @puhui999:参与,指的是有读写权限噢;可以把 1. 的合并到 2.2 里;因为 2.1 不需要; | ||
| 52 | if (CrmSceneTypeEnum.isInvolved(sceneType)) { | 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 | // 2.3 场景三:下属负责的数据 | 60 | // 2.3 场景三:下属负责的数据 |
| 56 | if (CrmSceneTypeEnum.isSubordinate(sceneType)) { | 61 | if (CrmSceneTypeEnum.isSubordinate(sceneType)) { |
| 57 | List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); | 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 | if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 | 70 | if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 |
| 66 | query.isNull("owner_user_id"); | 71 | query.isNull("owner_user_id"); |
| 67 | } else { // 情况二:不是公海 | 72 | } else { // 情况二:不是公海 |
| 68 | query.isNotNull("owner_user_id"); | 73 | query.isNotNull("owner_user_id"); |
| 69 | } | 74 | } |
| 75 | + | ||
| 76 | + return true; | ||
| 70 | } | 77 | } |
| 71 | 78 | ||
| 72 | /** | 79 | /** |
| 73 | * 构造 CRM 数据类型批量数据查询条件 | 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 | private static AdminUserApi getAdminUserApi() { | 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,7 +105,27 @@ public class CrmQueryWrapperUtils { | ||
| 101 | * @return 是/否 | 105 | * @return 是/否 |
| 102 | */ | 106 | */ |
| 103 | private static boolean validateAdminUser(Long userId) { | 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 | return false; | 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,12 +7,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv | ||
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; |
| 10 | +import jakarta.annotation.Resource; | ||
| 10 | import org.junit.jupiter.api.Disabled; | 11 | import org.junit.jupiter.api.Disabled; |
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | import org.springframework.context.annotation.Import; | 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 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 16 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 18 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 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,6 +22,7 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PL | ||
| 22 | import static org.junit.jupiter.api.Assertions.*; | 22 | import static org.junit.jupiter.api.Assertions.*; |
| 23 | 23 | ||
| 24 | // TODO 芋艿:后续,需要补充测试用例 | 24 | // TODO 芋艿:后续,需要补充测试用例 |
| 25 | + | ||
| 25 | /** | 26 | /** |
| 26 | * {@link CrmReceivablePlanServiceImpl} 的单元测试类 | 27 | * {@link CrmReceivablePlanServiceImpl} 的单元测试类 |
| 27 | * | 28 | * |
| @@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | @@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | ||
| 43 | CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class); | 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 | assertNotNull(receivablePlanId); | 49 | assertNotNull(receivablePlanId); |
| 49 | // 校验记录的属性是否正确 | 50 | // 校验记录的属性是否正确 |
| @@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | @@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | ||
| 87 | 88 | ||
| 88 | // 调用 | 89 | // 调用 |
| 89 | receivablePlanService.deleteReceivablePlan(id); | 90 | receivablePlanService.deleteReceivablePlan(id); |
| 90 | - // 校验数据不存在了 | ||
| 91 | - assertNull(crmReceivablePlanMapper.selectById(id)); | 91 | + // 校验数据不存在了 |
| 92 | + assertNull(crmReceivablePlanMapper.selectById(id)); | ||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | @Test | 95 | @Test |
| @@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | @@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { | ||
| 103 | @Test | 104 | @Test |
| 104 | @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | 105 | @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 |
| 105 | public void testGetReceivablePlanPage() { | 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,12 +7,11 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.Crm | ||
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; |
| 10 | +import jakarta.annotation.Resource; | ||
| 10 | import org.junit.jupiter.api.Disabled; | 11 | import org.junit.jupiter.api.Disabled; |
| 11 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 12 | import org.springframework.context.annotation.Import; | 13 | import org.springframework.context.annotation.Import; |
| 13 | 14 | ||
| 14 | -import jakarta.annotation.Resource; | ||
| 15 | - | ||
| 16 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 15 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 16 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 18 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | 17 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| @@ -133,7 +132,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest { | @@ -133,7 +132,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest { | ||
| 133 | reqVO.setCustomerId(null); | 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 | assertEquals(1, pageResult.getTotal()); | 137 | assertEquals(1, pageResult.getTotal()); |
| 139 | assertEquals(1, pageResult.getList().size()); | 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,7 +63,7 @@ export function export${simpleClassName}Excel(params) { | ||
| 63 | responseType: 'blob' | 63 | responseType: 'blob' |
| 64 | }) | 64 | }) |
| 65 | } | 65 | } |
| 66 | -## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对 | 66 | +## 特殊:主子表专属逻辑 |
| 67 | #foreach ($subTable in $subTables) | 67 | #foreach ($subTable in $subTables) |
| 68 | #set ($index = $foreach.count - 1) | 68 | #set ($index = $foreach.count - 1) |
| 69 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) | 69 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) |
| @@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) { | @@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) { | ||
| 76 | 76 | ||
| 77 | // ==================== 子表($subTable.classComment) ==================== | 77 | // ==================== 子表($subTable.classComment) ==================== |
| 78 | ## 情况一:MASTER_ERP 时,需要分查询页子表 | 78 | ## 情况一:MASTER_ERP 时,需要分查询页子表 |
| 79 | - #if ( $table.templateType == 11 ) | 79 | + #if ($table.templateType == 11) |
| 80 | // 获得${subTable.classComment}分页 | 80 | // 获得${subTable.classComment}分页 |
| 81 | export function get${subSimpleClassName}Page(params) { | 81 | export function get${subSimpleClassName}Page(params) { |
| 82 | return request({ | 82 | return request({ |
| @@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) { | @@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) { | ||
| 87 | } | 87 | } |
| 88 | ## 情况二:非 MASTER_ERP 时,需要列表查询子表 | 88 | ## 情况二:非 MASTER_ERP 时,需要列表查询子表 |
| 89 | #else | 89 | #else |
| 90 | - #if ( $subTable.subJoinMany ) | 90 | + #if ($subTable.subJoinMany) |
| 91 | // 获得${subTable.classComment}列表 | 91 | // 获得${subTable.classComment}列表 |
| 92 | export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { | 92 | export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { |
| 93 | return request({ | 93 | return request({ |
| @@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) { | @@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) { | ||
| 106 | #end | 106 | #end |
| 107 | #end | 107 | #end |
| 108 | ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 | 108 | ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 |
| 109 | - #if ( $table.templateType == 11 ) | 109 | + #if ($table.templateType == 11) |
| 110 | // 新增${subTable.classComment} | 110 | // 新增${subTable.classComment} |
| 111 | export function create${subSimpleClassName}(data) { | 111 | export function create${subSimpleClassName}(data) { |
| 112 | return request({ | 112 | return request({ |
| @@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) { | @@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) { | ||
| 115 | data | 115 | data |
| 116 | }) | 116 | }) |
| 117 | } | 117 | } |
| 118 | - | ||
| 119 | // 修改${subTable.classComment} | 118 | // 修改${subTable.classComment} |
| 120 | export function update${subSimpleClassName}(data) { | 119 | export function update${subSimpleClassName}(data) { |
| 121 | return request({ | 120 | return request({ |
| @@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) { | @@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) { | ||
| 124 | data | 123 | data |
| 125 | }) | 124 | }) |
| 126 | } | 125 | } |
| 127 | - | ||
| 128 | // 删除${subTable.classComment} | 126 | // 删除${subTable.classComment} |
| 129 | export function delete${subSimpleClassName}(id) { | 127 | export function delete${subSimpleClassName}(id) { |
| 130 | return request({ | 128 | return request({ |
| @@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) { | @@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) { | ||
| 132 | method: 'delete' | 130 | method: 'delete' |
| 133 | }) | 131 | }) |
| 134 | } | 132 | } |
| 135 | - | ||
| 136 | // 获得${subTable.classComment} | 133 | // 获得${subTable.classComment} |
| 137 | export function get${subSimpleClassName}(id) { | 134 | export function get${subSimpleClassName}(id) { |
| 138 | return request({ | 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,11 +7,10 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity | ||
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; |
| 9 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; | 9 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; |
| 10 | +import jakarta.annotation.Resource; | ||
| 10 | import org.springframework.stereotype.Service; | 11 | import org.springframework.stereotype.Service; |
| 11 | import org.springframework.validation.annotation.Validated; | 12 | import org.springframework.validation.annotation.Validated; |
| 12 | 13 | ||
| 13 | -import jakarta.annotation.Resource; | ||
| 14 | - | ||
| 15 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 14 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 16 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS; | 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,21 +24,21 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA | ||
| 25 | public class CombinationRecordApiImpl implements CombinationRecordApi { | 24 | public class CombinationRecordApiImpl implements CombinationRecordApi { |
| 26 | 25 | ||
| 27 | @Resource | 26 | @Resource |
| 28 | - private CombinationRecordService recordService; | 27 | + private CombinationRecordService combinationRecordService; |
| 29 | 28 | ||
| 30 | @Override | 29 | @Override |
| 31 | public void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count) { | 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 | @Override | 34 | @Override |
| 36 | public CombinationRecordCreateRespDTO createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | 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 | @Override | 39 | @Override |
| 41 | public boolean isCombinationRecordSuccess(Long userId, Long orderId) { | 40 | public boolean isCombinationRecordSuccess(Long userId, Long orderId) { |
| 42 | - CombinationRecordDO record = recordService.getCombinationRecord(userId, orderId); | 41 | + CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId); |
| 43 | if (record == null) { | 42 | if (record == null) { |
| 44 | throw exception(COMBINATION_RECORD_NOT_EXISTS); | 43 | throw exception(COMBINATION_RECORD_NOT_EXISTS); |
| 45 | } | 44 | } |
| @@ -48,7 +47,7 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | @@ -48,7 +47,7 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | ||
| 48 | 47 | ||
| 49 | @Override | 48 | @Override |
| 50 | public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) { | 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,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.util.ObjUtil; | 4 | import cn.hutool.core.util.ObjUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 7 | +import cn.iocoder.yudao.framework.common.util.date.DateUtils; | ||
| 7 | import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; | 8 | import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; |
| 8 | import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; | 9 | import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; |
| 9 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; | 10 | import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; |
| @@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert { | @@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert { | ||
| 47 | // 1. 计算是第几天签到 | 48 | // 1. 计算是第几天签到 |
| 48 | configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); | 49 | configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); |
| 49 | MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置 | 50 | MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置 |
| 50 | - // 1.2. 计算今天是第几天签到 | 51 | + // 1.2. 计算今天是第几天签到 (只有连续签到才加否则重置为 1) |
| 51 | int day = 1; | 52 | int day = 1; |
| 52 | - // TODO @puhui999:要判断是不是昨天签到的;是否是昨天的判断,可以抽个方法到 util 里 | ||
| 53 | - if (lastRecord != null) { | 53 | + if (lastRecord != null && DateUtils.isYesterday(lastRecord.getCreateTime())) { |
| 54 | day = lastRecord.getDay() + 1; | 54 | day = lastRecord.getDay() + 1; |
| 55 | } | 55 | } |
| 56 | // 1.3 判断是否超出了最大签到配置 | 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,14 +19,12 @@ import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | ||
| 19 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; | 19 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; |
| 20 | import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; | 20 | import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; |
| 21 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; | 21 | import cn.iocoder.yudao.module.member.service.user.MemberUserService; |
| 22 | +import jakarta.annotation.Resource; | ||
| 22 | import org.apache.commons.lang3.StringUtils; | 23 | import org.apache.commons.lang3.StringUtils; |
| 23 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 24 | import org.springframework.transaction.annotation.Transactional; | 25 | import org.springframework.transaction.annotation.Transactional; |
| 25 | import org.springframework.validation.annotation.Validated; | 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 | import java.util.List; | 28 | import java.util.List; |
| 31 | import java.util.Set; | 29 | import java.util.Set; |
| 32 | 30 | ||
| @@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | @@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService | ||
| 77 | } | 75 | } |
| 78 | summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime())); | 76 | summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime())); |
| 79 | 77 | ||
| 80 | - // 4. 校验今天是否签到,没有签到则直接返回 | 78 | + // 4.1 校验今天是否签到,没有签到则直接返回 |
| 81 | if (!summary.getTodaySignIn()) { | 79 | if (!summary.getTodaySignIn()) { |
| 82 | return summary; | 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 | return summary; | 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 | @Override | 87 | @Override |
| 125 | public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { | 88 | public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { |
| 126 | // 根据用户昵称查询出用户ids | 89 | // 根据用户昵称查询出用户ids |
yudao-module-system/yudao-module-system-api/pom.xml
| @@ -22,6 +22,23 @@ | @@ -22,6 +22,23 @@ | ||
| 22 | <artifactId>yudao-common</artifactId> | 22 | <artifactId>yudao-common</artifactId> |
| 23 | </dependency> | 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 | <dependency> | 43 | <dependency> |
| 27 | <groupId>org.springframework.boot</groupId> | 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 | package cn.iocoder.yudao.module.system.api.logger; | 1 | package cn.iocoder.yudao.module.system.api.logger; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 3 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 4 | - | 4 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; |
| 5 | import jakarta.validation.Valid; | 5 | import jakarta.validation.Valid; |
| 6 | 6 | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 7 | /** | 9 | /** |
| 8 | * 操作日志 API 接口 | 10 | * 操作日志 API 接口 |
| 9 | * | 11 | * |
| @@ -18,4 +20,13 @@ public interface OperateLogApi { | @@ -18,4 +20,13 @@ public interface OperateLogApi { | ||
| 18 | */ | 20 | */ |
| 19 | void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); | 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 | package cn.iocoder.yudao.module.system.api.logger; | 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 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 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 | import cn.iocoder.yudao.module.system.service.logger.OperateLogService; | 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 | import org.springframework.stereotype.Service; | 12 | import org.springframework.stereotype.Service; |
| 6 | import org.springframework.validation.annotation.Validated; | 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 | * 操作日志 API 实现类 | 23 | * 操作日志 API 实现类 |
| @@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi { | @@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi { | ||
| 18 | 30 | ||
| 19 | @Resource | 31 | @Resource |
| 20 | private OperateLogService operateLogService; | 32 | private OperateLogService operateLogService; |
| 33 | + @Resource | ||
| 34 | + private AdminUserService adminUserService; | ||
| 21 | 35 | ||
| 22 | @Override | 36 | @Override |
| 23 | public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { | 37 | public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { |
| 24 | operateLogService.createOperateLog(createReqDTO); | 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,6 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; | 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 | * 操作日志 Service 接口 | 13 | * 操作日志 Service 接口 |
| @@ -27,4 +31,22 @@ public interface OperateLogService { | @@ -27,4 +31,22 @@ public interface OperateLogService { | ||
| 27 | */ | 31 | */ |
| 28 | PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO); | 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,15 +8,19 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; | ||
| 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 9 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; |
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | ||
| 11 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 12 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; | 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 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 16 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 17 | +import jakarta.annotation.Resource; | ||
| 14 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
| 15 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
| 16 | import org.springframework.validation.annotation.Validated; | 20 | import org.springframework.validation.annotation.Validated; |
| 17 | 21 | ||
| 18 | -import jakarta.annotation.Resource; | ||
| 19 | import java.util.Collection; | 22 | import java.util.Collection; |
| 23 | +import java.util.List; | ||
| 20 | 24 | ||
| 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 22 | import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; | 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,6 +38,8 @@ public class OperateLogServiceImpl implements OperateLogService { | ||
| 34 | 38 | ||
| 35 | @Resource | 39 | @Resource |
| 36 | private OperateLogMapper operateLogMapper; | 40 | private OperateLogMapper operateLogMapper; |
| 41 | + @Resource | ||
| 42 | + private OperateLogV2Mapper operateLogV2Mapper; | ||
| 37 | 43 | ||
| 38 | @Resource | 44 | @Resource |
| 39 | private AdminUserService userService; | 45 | private AdminUserService userService; |
| @@ -60,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService { | @@ -60,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService { | ||
| 60 | return operateLogMapper.selectPage(pageReqVO, userIds); | 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 | +} |