Commit 89fc83c41938d0fd88337507c0190fdcaba6ff41
1 parent
e2ec426a
CRM:code review 客户权限的实现
Showing
21 changed files
with
71 additions
and
42 deletions
sql/mysql/ruoyi-vue-pro.sql
yudao-dependencies/pom.xml
| @@ -627,11 +627,11 @@ | @@ -627,11 +627,11 @@ | ||
| 627 | <artifactId>ureport2-console</artifactId> | 627 | <artifactId>ureport2-console</artifactId> |
| 628 | <version>${ureport2.version}</version> | 628 | <version>${ureport2.version}</version> |
| 629 | <exclusions> | 629 | <exclusions> |
| 630 | - <exclusion><!-- 包冲突 积木报表 导出Excel报错 --> | 630 | + <exclusion><!-- 包冲突:解决积木报表导出 Excel 报错 --> |
| 631 | <groupId>org.apache.poi</groupId> | 631 | <groupId>org.apache.poi</groupId> |
| 632 | <artifactId>poi</artifactId> | 632 | <artifactId>poi</artifactId> |
| 633 | </exclusion> | 633 | </exclusion> |
| 634 | - <exclusion><!-- 包冲突 积木报表 导出Excel报错 --> | 634 | + <exclusion><!-- 包冲突:解决积木报表导出 Excel 报错 --> |
| 635 | <groupId>org.apache.poi</groupId> | 635 | <groupId>org.apache.poi</groupId> |
| 636 | <artifactId>poi-ooxml</artifactId> | 636 | <artifactId>poi-ooxml</artifactId> |
| 637 | </exclusion> | 637 | </exclusion> |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/MapUtils.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.CollectionUtil; | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | +import cn.hutool.core.util.ObjUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 6 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 6 | import com.google.common.collect.Maps; | 7 | import com.google.common.collect.Maps; |
| 7 | import com.google.common.collect.Multimap; | 8 | import com.google.common.collect.Multimap; |
| @@ -40,6 +41,7 @@ public class MapUtils { | @@ -40,6 +41,7 @@ public class MapUtils { | ||
| 40 | 41 | ||
| 41 | /** | 42 | /** |
| 42 | * 从哈希表查找到 key 对应的 value,然后进一步处理 | 43 | * 从哈希表查找到 key 对应的 value,然后进一步处理 |
| 44 | + * key 为 null 时, 不处理 | ||
| 43 | * 注意,如果查找到的 value 为 null 时,不进行处理 | 45 | * 注意,如果查找到的 value 为 null 时,不进行处理 |
| 44 | * | 46 | * |
| 45 | * @param map 哈希表 | 47 | * @param map 哈希表 |
| @@ -47,7 +49,7 @@ public class MapUtils { | @@ -47,7 +49,7 @@ public class MapUtils { | ||
| 47 | * @param consumer 进一步处理的逻辑 | 49 | * @param consumer 进一步处理的逻辑 |
| 48 | */ | 50 | */ |
| 49 | public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) { | 51 | public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) { |
| 50 | - if (CollUtil.isEmpty(map)) { | 52 | + if (ObjUtil.isNull(key) || CollUtil.isEmpty(map)) { |
| 51 | return; | 53 | return; |
| 52 | } | 54 | } |
| 53 | V value = map.get(key); | 55 | V value = map.get(key); |
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/core/DictFrameworkUtils.java
| @@ -13,8 +13,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -13,8 +13,6 @@ import lombok.extern.slf4j.Slf4j; | ||
| 13 | import java.time.Duration; | 13 | import java.time.Duration; |
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | 15 | ||
| 16 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 17 | - | ||
| 18 | /** | 16 | /** |
| 19 | * 字典工具类 | 17 | * 字典工具类 |
| 20 | * | 18 | * |
| @@ -27,6 +25,7 @@ public class DictFrameworkUtils { | @@ -27,6 +25,7 @@ public class DictFrameworkUtils { | ||
| 27 | 25 | ||
| 28 | private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO(); | 26 | private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO(); |
| 29 | 27 | ||
| 28 | + // TODO @puhui999:GET_DICT_DATA_CACHE、GET_DICT_DATA_LIST_CACHE、PARSE_DICT_DATA_CACHE 这 3 个缓存是有点重叠,可以思考下,有没可能减少 1 个。微信讨论好私聊,再具体改哈 | ||
| 30 | /** | 29 | /** |
| 31 | * 针对 {@link #getDictDataLabel(String, String)} 的缓存 | 30 | * 针对 {@link #getDictDataLabel(String, String)} 的缓存 |
| 32 | */ | 31 | */ |
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/annotations/ExcelColumnSelect.java
| @@ -3,7 +3,9 @@ package cn.iocoder.yudao.framework.excel.core.annotations; | @@ -3,7 +3,9 @@ package cn.iocoder.yudao.framework.excel.core.annotations; | ||
| 3 | import java.lang.annotation.*; | 3 | import java.lang.annotation.*; |
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | - * 给列添加下拉选择数据 | 6 | + * 给 Excel 列添加下拉选择数据 |
| 7 | + * | ||
| 8 | + * 其中 {@link #dictType()} 和 {@link #functionName()} 二选一 | ||
| 7 | * | 9 | * |
| 8 | * @author HUIHUI | 10 | * @author HUIHUI |
| 9 | */ | 11 | */ |
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java
| 1 | package cn.iocoder.yudao.framework.excel.core.handler; | 1 | package cn.iocoder.yudao.framework.excel.core.handler; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 5 | -import cn.hutool.core.util.ObjUtil; | 6 | +import cn.hutool.core.util.ObjectUtil; |
| 6 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 7 | import cn.hutool.extra.spring.SpringUtil; | 8 | import cn.hutool.extra.spring.SpringUtil; |
| 8 | import cn.hutool.poi.excel.ExcelUtil; | 9 | import cn.hutool.poi.excel.ExcelUtil; |
| @@ -59,7 +60,6 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | @@ -59,7 +60,6 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | ||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | // 解析下拉数据 | 62 | // 解析下拉数据 |
| 62 | - // TODO @puhui999:感觉可以 head 循环 field,如果有 ExcelColumnSelect 则进行处理;而 ExcelProperty 可能是非必须的。回答:主要是用于定位到列索引 | ||
| 63 | Map<String, Field> excelPropertyFields = getFieldsWithAnnotation(head, ExcelProperty.class); | 63 | Map<String, Field> excelPropertyFields = getFieldsWithAnnotation(head, ExcelProperty.class); |
| 64 | Map<String, Field> excelColumnSelectFields = getFieldsWithAnnotation(head, ExcelColumnSelect.class); | 64 | Map<String, Field> excelColumnSelectFields = getFieldsWithAnnotation(head, ExcelColumnSelect.class); |
| 65 | int colIndex = 0; | 65 | int colIndex = 0; |
| @@ -71,39 +71,47 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | @@ -71,39 +71,47 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | ||
| 71 | if (index != -1) { | 71 | if (index != -1) { |
| 72 | colIndex = index; | 72 | colIndex = index; |
| 73 | } | 73 | } |
| 74 | - getSelectDataList(colIndex, field); | 74 | + buildSelectDataList(colIndex, field); |
| 75 | } | 75 | } |
| 76 | colIndex++; | 76 | colIndex++; |
| 77 | } | 77 | } |
| 78 | + // TODO @puhui999:感觉可以 head 循环 field,如果有 ExcelColumnSelect 则进行处理;而 ExcelProperty 可能是非必须的。回答:主要是用于定位到列索引;补充:可以看看下面这样写? | ||
| 79 | +// for (Field field : head.getDeclaredFields()) { | ||
| 80 | +// if (field.isAnnotationPresent(ExcelColumnSelect.class)) { | ||
| 81 | +// ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); | ||
| 82 | +// if (excelProperty != null) { | ||
| 83 | +// colIndex = excelProperty.index(); | ||
| 84 | +// } | ||
| 85 | +// getSelectDataList(colIndex, field); | ||
| 86 | +// } | ||
| 87 | +// colIndex++; | ||
| 88 | +// } | ||
| 78 | } | 89 | } |
| 79 | 90 | ||
| 80 | /** | 91 | /** |
| 81 | - * 获得下拉数据 | 92 | + * 获得下拉数据,并添加到 {@link #selectMap} 中 |
| 82 | * | 93 | * |
| 83 | * @param colIndex 列索引 | 94 | * @param colIndex 列索引 |
| 84 | * @param field 字段 | 95 | * @param field 字段 |
| 85 | */ | 96 | */ |
| 86 | - private void getSelectDataList(int colIndex, Field field) { | ||
| 87 | - // 获得下拉注解信息 | 97 | + private void buildSelectDataList(int colIndex, Field field) { |
| 88 | ExcelColumnSelect columnSelect = field.getAnnotation(ExcelColumnSelect.class); | 98 | ExcelColumnSelect columnSelect = field.getAnnotation(ExcelColumnSelect.class); |
| 89 | String dictType = columnSelect.dictType(); | 99 | String dictType = columnSelect.dictType(); |
| 100 | + String functionName = columnSelect.functionName(); | ||
| 101 | + Assert.isTrue(ObjectUtil.isNotEmpty(dictType) || ObjectUtil.isNotEmpty(functionName), | ||
| 102 | + "Field({}) 的 @ExcelColumnSelect 注解,dictType 和 functionName 不能同时为空", field.getName()); | ||
| 103 | + | ||
| 104 | + // 情况一:使用 dictType 获得下拉数据 | ||
| 90 | if (StrUtil.isNotEmpty(dictType)) { // 情况一: 字典数据 (默认) | 105 | if (StrUtil.isNotEmpty(dictType)) { // 情况一: 字典数据 (默认) |
| 91 | selectMap.put(colIndex, DictFrameworkUtils.getDictDataLabelList(dictType)); | 106 | selectMap.put(colIndex, DictFrameworkUtils.getDictDataLabelList(dictType)); |
| 92 | return; | 107 | return; |
| 93 | } | 108 | } |
| 94 | - String functionName = columnSelect.functionName(); | ||
| 95 | - if (StrUtil.isEmpty(functionName)) { // 情况二: 获取自定义数据 | ||
| 96 | - log.warn("[getSelectDataList]解析下拉数据失败,参数信息 dictType[{}] functionName[{}]", dictType, functionName); | ||
| 97 | - return; | ||
| 98 | - } | ||
| 99 | - // 获得所有的下拉数据源获取方法 | 109 | + |
| 110 | + // 情况二:使用 functionName 获得下拉数据 | ||
| 100 | Map<String, ExcelColumnSelectFunction> functionMap = SpringUtil.getApplicationContext().getBeansOfType(ExcelColumnSelectFunction.class); | 111 | Map<String, ExcelColumnSelectFunction> functionMap = SpringUtil.getApplicationContext().getBeansOfType(ExcelColumnSelectFunction.class); |
| 101 | - functionMap.values().forEach(func -> { | ||
| 102 | - if (ObjUtil.notEqual(func.getName(), functionName)) { | ||
| 103 | - return; | ||
| 104 | - } | ||
| 105 | - selectMap.put(colIndex, func.getOptions()); | ||
| 106 | - }); | 112 | + ExcelColumnSelectFunction function = CollUtil.findOne(functionMap.values(), item -> item.getName().equals(functionName)); |
| 113 | + Assert.notNull(function, "未找到对应的 function({})", functionName); | ||
| 114 | + selectMap.put(colIndex, function.getOptions()); | ||
| 107 | } | 115 | } |
| 108 | 116 | ||
| 109 | @Override | 117 | @Override |
| @@ -121,7 +129,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | @@ -121,7 +129,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { | ||
| 121 | Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME); | 129 | Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME); |
| 122 | for (KeyValue<Integer, List<String>> keyValue : keyValues) { | 130 | for (KeyValue<Integer, List<String>> keyValue : keyValues) { |
| 123 | int rowLength = keyValue.getValue().size(); | 131 | int rowLength = keyValue.getValue().size(); |
| 124 | - // 2.1 设置字典 sheet 页的值 每一列一个字典项 | 132 | + // 2.1 设置字典 sheet 页的值,每一列一个字典项 |
| 125 | for (int i = 0; i < rowLength; i++) { | 133 | for (int i = 0; i < rowLength; i++) { |
| 126 | Row row = dictSheet.getRow(i); | 134 | Row row = dictSheet.getRow(i); |
| 127 | if (row == null) { | 135 | if (row == null) { |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java
| @@ -13,6 +13,7 @@ import lombok.NoArgsConstructor; | @@ -13,6 +13,7 @@ import lombok.NoArgsConstructor; | ||
| 13 | @AllArgsConstructor | 13 | @AllArgsConstructor |
| 14 | public class CrmBusinessTransferReqVO { | 14 | public class CrmBusinessTransferReqVO { |
| 15 | 15 | ||
| 16 | + // TODO @puhui999:这里最好还是用 id 哈,主要还是在 Business 业务里 | ||
| 16 | @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | 17 | @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 17 | @NotNull(message = "商机编号不能为空") | 18 | @NotNull(message = "商机编号不能为空") |
| 18 | private Long bizId; | 19 | private Long bizId; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java
| @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | ||
| 4 | import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; | 4 | import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; |
| 5 | import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; | 5 | import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; |
| 6 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | 6 | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| 7 | -import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunctionImpl; | 7 | +import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction; |
| 8 | import com.alibaba.excel.annotation.ExcelProperty; | 8 | import com.alibaba.excel.annotation.ExcelProperty; |
| 9 | import lombok.AllArgsConstructor; | 9 | import lombok.AllArgsConstructor; |
| 10 | import lombok.Builder; | 10 | import lombok.Builder; |
| @@ -43,7 +43,7 @@ public class CrmCustomerImportExcelVO { | @@ -43,7 +43,7 @@ public class CrmCustomerImportExcelVO { | ||
| 43 | private String email; | 43 | private String email; |
| 44 | 44 | ||
| 45 | @ExcelProperty(value = "地区", converter = AreaConvert.class) | 45 | @ExcelProperty(value = "地区", converter = AreaConvert.class) |
| 46 | - @ExcelColumnSelect(functionName = AreaExcelColumnSelectFunctionImpl.NAME) | 46 | + @ExcelColumnSelect(functionName = AreaExcelColumnSelectFunction.NAME) |
| 47 | private Integer areaId; | 47 | private Integer areaId; |
| 48 | 48 | ||
| 49 | @ExcelProperty("详细地址") | 49 | @ExcelProperty("详细地址") |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerTransferReqVO.java
| @@ -31,7 +31,7 @@ public class CrmCustomerTransferReqVO { | @@ -31,7 +31,7 @@ public class CrmCustomerTransferReqVO { | ||
| 31 | private Integer oldOwnerPermissionLevel; | 31 | private Integer oldOwnerPermissionLevel; |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | - * 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择 | 34 | + * 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择。选中时,也一起转移 |
| 35 | */ | 35 | */ |
| 36 | @Schema(description = "同时转移", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | 36 | @Schema(description = "同时转移", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 37 | private List<Integer> toBizTypes; | 37 | private List<Integer> toBizTypes; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java
| @@ -68,22 +68,24 @@ public class CrmPermissionController { | @@ -68,22 +68,24 @@ public class CrmPermissionController { | ||
| 68 | @Resource | 68 | @Resource |
| 69 | private PostApi postApi; | 69 | private PostApi postApi; |
| 70 | 70 | ||
| 71 | + // TODO @puhui999:是不是还是叫 create 好点哈。 | ||
| 71 | @PostMapping("/create") | 72 | @PostMapping("/create") |
| 72 | @Operation(summary = "创建数据权限") | 73 | @Operation(summary = "创建数据权限") |
| 73 | @Transactional(rollbackFor = Exception.class) | 74 | @Transactional(rollbackFor = Exception.class) |
| 74 | @PreAuthorize("@ss.hasPermission('crm:permission:create')") | 75 | @PreAuthorize("@ss.hasPermission('crm:permission:create')") |
| 75 | @CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER) | 76 | @CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER) |
| 76 | - public CommonResult<Boolean> addPermission(@Valid @RequestBody CrmPermissionSaveReqVO reqVO) { | 77 | + public CommonResult<Boolean> savePermission(@Valid @RequestBody CrmPermissionSaveReqVO reqVO) { |
| 77 | permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class)); | 78 | permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class)); |
| 79 | + // 处理【同时添加至】的权限 | ||
| 78 | if (CollUtil.isNotEmpty(reqVO.getToBizTypes())) { | 80 | if (CollUtil.isNotEmpty(reqVO.getToBizTypes())) { |
| 79 | createBizTypePermissions(reqVO); | 81 | createBizTypePermissions(reqVO); |
| 80 | } | 82 | } |
| 81 | return success(true); | 83 | return success(true); |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | - | ||
| 85 | private void createBizTypePermissions(CrmPermissionSaveReqVO reqVO) { | 86 | private void createBizTypePermissions(CrmPermissionSaveReqVO reqVO) { |
| 86 | List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>(); | 87 | List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>(); |
| 88 | + // TODO @puhui999:需要考虑,被添加人,是不是应该有对应的权限了; | ||
| 87 | if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) { | 89 | if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) { |
| 88 | List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getBizId(), getLoginUserId()); | 90 | List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getBizId(), getLoginUserId()); |
| 89 | contactList.forEach(item -> { | 91 | contactList.forEach(item -> { |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionSaveReqVO.java
| @@ -33,7 +33,8 @@ public class CrmPermissionSaveReqVO { | @@ -33,7 +33,8 @@ public class CrmPermissionSaveReqVO { | ||
| 33 | private Integer level; | 33 | private Integer level; |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | - * 添加客户团队成员时,需要额外有【联系人】【商机】【合同】的 checkbox 选择 | 36 | + * 添加客户团队成员时,需要额外有【联系人】【商机】【合同】的 checkbox 选择。 |
| 37 | + * 选中时,同时添加对应的权限 | ||
| 37 | */ | 38 | */ |
| 38 | @Schema(description = "同时添加", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") | 39 | @Schema(description = "同时添加", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") |
| 39 | private List<Integer> toBizTypes; | 40 | private List<Integer> toBizTypes; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
| @@ -74,6 +74,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | @@ -74,6 +74,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | ||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | default List<CrmContactDO> selectListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId) { | 76 | default List<CrmContactDO> selectListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId) { |
| 77 | + // TODO @puhui999:父类有 selectList,查询 2 个字段的简化方法哈,可以用下 | ||
| 77 | return selectList(new LambdaQueryWrapperX<CrmContactDO>() | 78 | return selectList(new LambdaQueryWrapperX<CrmContactDO>() |
| 78 | .eq(CrmContactDO::getCustomerId, customerId) | 79 | .eq(CrmContactDO::getCustomerId, customerId) |
| 79 | .eq(CrmContactDO::getOwnerUserId, ownerUserId)); | 80 | .eq(CrmContactDO::getOwnerUserId, ownerUserId)); |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
| @@ -99,4 +99,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | @@ -99,4 +99,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | ||
| 99 | return convertMap(result, obj -> (Long) obj.get("contract_id"), obj -> (BigDecimal) obj.get("total_price")); | 99 | return convertMap(result, obj -> (Long) obj.get("contract_id"), obj -> (BigDecimal) obj.get("total_price")); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | + default Long selectCountByContractId(Long contractId) { | ||
| 103 | + return selectCount(CrmReceivableDO::getContractId, contractId); | ||
| 104 | + } | ||
| 105 | + | ||
| 102 | } | 106 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunctionImpl.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunction.java
| @@ -10,10 +10,12 @@ import java.util.List; | @@ -10,10 +10,12 @@ import java.util.List; | ||
| 10 | /** | 10 | /** |
| 11 | * Excel 所属地区列下拉数据源获取接口实现类 | 11 | * Excel 所属地区列下拉数据源获取接口实现类 |
| 12 | * | 12 | * |
| 13 | + * // TODO @puhui999:类名叫:地区下拉框数据源的 {@link ExcelColumnSelectFunction} 实现类,这样看起来会更简洁一点哈 | ||
| 14 | + * | ||
| 13 | * @author HUIHUI | 15 | * @author HUIHUI |
| 14 | */ | 16 | */ |
| 15 | @Service | 17 | @Service |
| 16 | -public class AreaExcelColumnSelectFunctionImpl implements ExcelColumnSelectFunction { | 18 | +public class AreaExcelColumnSelectFunction implements ExcelColumnSelectFunction { |
| 17 | 19 | ||
| 18 | public static final String NAME = "getCrmAreaNameList"; // 防止和别的模块重名 | 20 | public static final String NAME = "getCrmAreaNameList"; // 防止和别的模块重名 |
| 19 | 21 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/package-info.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
| @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.collection.ListUtil; | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | import cn.hutool.core.lang.Assert; | 5 | import cn.hutool.core.lang.Assert; |
| 6 | import cn.hutool.core.util.ObjUtil; | 6 | import cn.hutool.core.util.ObjUtil; |
| 7 | -import cn.hutool.extra.spring.SpringUtil; | ||
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; | 8 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; |
| 10 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 9 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| @@ -27,7 +26,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm | @@ -27,7 +26,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm | ||
| 27 | import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | 26 | import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; |
| 28 | import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | 27 | import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; |
| 29 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 28 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 30 | -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerServiceImpl; | ||
| 31 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 29 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 32 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 30 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 33 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | 31 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; |
| @@ -231,7 +229,7 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -231,7 +229,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 231 | // 1.1 校验存在 | 229 | // 1.1 校验存在 |
| 232 | CrmContractDO contract = validateContractExists(id); | 230 | CrmContractDO contract = validateContractExists(id); |
| 233 | // 1.2 如果被 CrmReceivableDO 所使用,则不允许删除 | 231 | // 1.2 如果被 CrmReceivableDO 所使用,则不允许删除 |
| 234 | - if (receivableService.getReceivableByContractId(contract.getId()) != 0) { | 232 | + if (receivableService.getReceivableCountByContractId(contract.getId()) > 0) { |
| 235 | throw exception(CONTRACT_DELETE_FAIL); | 233 | throw exception(CONTRACT_DELETE_FAIL); |
| 236 | } | 234 | } |
| 237 | 235 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
| @@ -123,11 +123,11 @@ public interface CrmReceivableService { | @@ -123,11 +123,11 @@ public interface CrmReceivableService { | ||
| 123 | Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds); | 123 | Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds); |
| 124 | 124 | ||
| 125 | /** | 125 | /** |
| 126 | - * 更具合同编号查询回款列表 | 126 | + * 根据合同编号查询回款数量 |
| 127 | * | 127 | * |
| 128 | * @param contractId 合同编号 | 128 | * @param contractId 合同编号 |
| 129 | - * @return 回款 | 129 | + * @return 回款数量 |
| 130 | */ | 130 | */ |
| 131 | - Long getReceivableByContractId(Long contractId); | 131 | + Long getReceivableCountByContractId(Long contractId); |
| 132 | 132 | ||
| 133 | } | 133 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
| @@ -302,8 +302,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -302,8 +302,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | @Override | 304 | @Override |
| 305 | - public Long getReceivableByContractId(Long contractId) { | ||
| 306 | - return receivableMapper.selectCount(CrmReceivableDO::getContractId, contractId); | 305 | + public Long getReceivableCountByContractId(Long contractId) { |
| 306 | + return receivableMapper.selectCountByContractId(contractId); | ||
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | } | 309 | } |