CRM:code review 客户权限的实现
This commit is contained in:
parent
e2ec426a9f
commit
89fc83c419
@ -11,7 +11,7 @@
|
|||||||
Target Server Version : 80200 (8.2.0)
|
Target Server Version : 80200 (8.2.0)
|
||||||
File Encoding : 65001
|
File Encoding : 65001
|
||||||
|
|
||||||
Date: 01/03/2024 19:39:45
|
Date: 05/03/2024 23:36:35
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
|
@ -627,11 +627,11 @@
|
|||||||
<artifactId>ureport2-console</artifactId>
|
<artifactId>ureport2-console</artifactId>
|
||||||
<version>${ureport2.version}</version>
|
<version>${ureport2.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion><!-- 包冲突 积木报表 导出Excel报错 -->
|
<exclusion><!-- 包冲突:解决积木报表导出 Excel 报错 -->
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi</artifactId>
|
<artifactId>poi</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion><!-- 包冲突 积木报表 导出Excel报错 -->
|
<exclusion><!-- 包冲突:解决积木报表导出 Excel 报错 -->
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
@ -40,6 +41,7 @@ public class MapUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 从哈希表查找到 key 对应的 value,然后进一步处理
|
* 从哈希表查找到 key 对应的 value,然后进一步处理
|
||||||
|
* key 为 null 时, 不处理
|
||||||
* 注意,如果查找到的 value 为 null 时,不进行处理
|
* 注意,如果查找到的 value 为 null 时,不进行处理
|
||||||
*
|
*
|
||||||
* @param map 哈希表
|
* @param map 哈希表
|
||||||
@ -47,7 +49,7 @@ public class MapUtils {
|
|||||||
* @param consumer 进一步处理的逻辑
|
* @param consumer 进一步处理的逻辑
|
||||||
*/
|
*/
|
||||||
public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) {
|
public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) {
|
||||||
if (CollUtil.isEmpty(map)) {
|
if (ObjUtil.isNull(key) || CollUtil.isEmpty(map)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
V value = map.get(key);
|
V value = map.get(key);
|
||||||
|
@ -13,8 +13,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字典工具类
|
* 字典工具类
|
||||||
*
|
*
|
||||||
@ -27,6 +25,7 @@ public class DictFrameworkUtils {
|
|||||||
|
|
||||||
private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO();
|
private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO();
|
||||||
|
|
||||||
|
// TODO @puhui999:GET_DICT_DATA_CACHE、GET_DICT_DATA_LIST_CACHE、PARSE_DICT_DATA_CACHE 这 3 个缓存是有点重叠,可以思考下,有没可能减少 1 个。微信讨论好私聊,再具体改哈
|
||||||
/**
|
/**
|
||||||
* 针对 {@link #getDictDataLabel(String, String)} 的缓存
|
* 针对 {@link #getDictDataLabel(String, String)} 的缓存
|
||||||
*/
|
*/
|
||||||
|
@ -3,7 +3,9 @@ package cn.iocoder.yudao.framework.excel.core.annotations;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给列添加下拉选择数据
|
* 给 Excel 列添加下拉选择数据
|
||||||
|
*
|
||||||
|
* 其中 {@link #dictType()} 和 {@link #functionName()} 二选一
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package cn.iocoder.yudao.framework.excel.core.handler;
|
package cn.iocoder.yudao.framework.excel.core.handler;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.hutool.poi.excel.ExcelUtil;
|
import cn.hutool.poi.excel.ExcelUtil;
|
||||||
@ -59,7 +60,6 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 解析下拉数据
|
// 解析下拉数据
|
||||||
// TODO @puhui999:感觉可以 head 循环 field,如果有 ExcelColumnSelect 则进行处理;而 ExcelProperty 可能是非必须的。回答:主要是用于定位到列索引
|
|
||||||
Map<String, Field> excelPropertyFields = getFieldsWithAnnotation(head, ExcelProperty.class);
|
Map<String, Field> excelPropertyFields = getFieldsWithAnnotation(head, ExcelProperty.class);
|
||||||
Map<String, Field> excelColumnSelectFields = getFieldsWithAnnotation(head, ExcelColumnSelect.class);
|
Map<String, Field> excelColumnSelectFields = getFieldsWithAnnotation(head, ExcelColumnSelect.class);
|
||||||
int colIndex = 0;
|
int colIndex = 0;
|
||||||
@ -71,39 +71,47 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
colIndex = index;
|
colIndex = index;
|
||||||
}
|
}
|
||||||
getSelectDataList(colIndex, field);
|
buildSelectDataList(colIndex, field);
|
||||||
}
|
}
|
||||||
colIndex++;
|
colIndex++;
|
||||||
}
|
}
|
||||||
|
// TODO @puhui999:感觉可以 head 循环 field,如果有 ExcelColumnSelect 则进行处理;而 ExcelProperty 可能是非必须的。回答:主要是用于定位到列索引;补充:可以看看下面这样写?
|
||||||
|
// for (Field field : head.getDeclaredFields()) {
|
||||||
|
// if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
|
||||||
|
// ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
|
||||||
|
// if (excelProperty != null) {
|
||||||
|
// colIndex = excelProperty.index();
|
||||||
|
// }
|
||||||
|
// getSelectDataList(colIndex, field);
|
||||||
|
// }
|
||||||
|
// colIndex++;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得下拉数据
|
* 获得下拉数据,并添加到 {@link #selectMap} 中
|
||||||
*
|
*
|
||||||
* @param colIndex 列索引
|
* @param colIndex 列索引
|
||||||
* @param field 字段
|
* @param field 字段
|
||||||
*/
|
*/
|
||||||
private void getSelectDataList(int colIndex, Field field) {
|
private void buildSelectDataList(int colIndex, Field field) {
|
||||||
// 获得下拉注解信息
|
|
||||||
ExcelColumnSelect columnSelect = field.getAnnotation(ExcelColumnSelect.class);
|
ExcelColumnSelect columnSelect = field.getAnnotation(ExcelColumnSelect.class);
|
||||||
String dictType = columnSelect.dictType();
|
String dictType = columnSelect.dictType();
|
||||||
|
String functionName = columnSelect.functionName();
|
||||||
|
Assert.isTrue(ObjectUtil.isNotEmpty(dictType) || ObjectUtil.isNotEmpty(functionName),
|
||||||
|
"Field({}) 的 @ExcelColumnSelect 注解,dictType 和 functionName 不能同时为空", field.getName());
|
||||||
|
|
||||||
|
// 情况一:使用 dictType 获得下拉数据
|
||||||
if (StrUtil.isNotEmpty(dictType)) { // 情况一: 字典数据 (默认)
|
if (StrUtil.isNotEmpty(dictType)) { // 情况一: 字典数据 (默认)
|
||||||
selectMap.put(colIndex, DictFrameworkUtils.getDictDataLabelList(dictType));
|
selectMap.put(colIndex, DictFrameworkUtils.getDictDataLabelList(dictType));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String functionName = columnSelect.functionName();
|
|
||||||
if (StrUtil.isEmpty(functionName)) { // 情况二: 获取自定义数据
|
// 情况二:使用 functionName 获得下拉数据
|
||||||
log.warn("[getSelectDataList]解析下拉数据失败,参数信息 dictType[{}] functionName[{}]", dictType, functionName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 获得所有的下拉数据源获取方法
|
|
||||||
Map<String, ExcelColumnSelectFunction> functionMap = SpringUtil.getApplicationContext().getBeansOfType(ExcelColumnSelectFunction.class);
|
Map<String, ExcelColumnSelectFunction> functionMap = SpringUtil.getApplicationContext().getBeansOfType(ExcelColumnSelectFunction.class);
|
||||||
functionMap.values().forEach(func -> {
|
ExcelColumnSelectFunction function = CollUtil.findOne(functionMap.values(), item -> item.getName().equals(functionName));
|
||||||
if (ObjUtil.notEqual(func.getName(), functionName)) {
|
Assert.notNull(function, "未找到对应的 function({})", functionName);
|
||||||
return;
|
selectMap.put(colIndex, function.getOptions());
|
||||||
}
|
|
||||||
selectMap.put(colIndex, func.getOptions());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -121,7 +129,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
|
|||||||
Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME);
|
Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME);
|
||||||
for (KeyValue<Integer, List<String>> keyValue : keyValues) {
|
for (KeyValue<Integer, List<String>> keyValue : keyValues) {
|
||||||
int rowLength = keyValue.getValue().size();
|
int rowLength = keyValue.getValue().size();
|
||||||
// 2.1 设置字典 sheet 页的值 每一列一个字典项
|
// 2.1 设置字典 sheet 页的值,每一列一个字典项
|
||||||
for (int i = 0; i < rowLength; i++) {
|
for (int i = 0; i < rowLength; i++) {
|
||||||
Row row = dictSheet.getRow(i);
|
Row row = dictSheet.getRow(i);
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
|
@ -13,6 +13,7 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class CrmBusinessTransferReqVO {
|
public class CrmBusinessTransferReqVO {
|
||||||
|
|
||||||
|
// TODO @puhui999:这里最好还是用 id 哈,主要还是在 Business 业务里
|
||||||
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||||
@NotNull(message = "商机编号不能为空")
|
@NotNull(message = "商机编号不能为空")
|
||||||
private Long bizId;
|
private Long bizId;
|
||||||
|
@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
|||||||
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
|
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
|
||||||
import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert;
|
import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert;
|
||||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||||
import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunctionImpl;
|
import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@ -43,7 +43,7 @@ public class CrmCustomerImportExcelVO {
|
|||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@ExcelProperty(value = "地区", converter = AreaConvert.class)
|
@ExcelProperty(value = "地区", converter = AreaConvert.class)
|
||||||
@ExcelColumnSelect(functionName = AreaExcelColumnSelectFunctionImpl.NAME)
|
@ExcelColumnSelect(functionName = AreaExcelColumnSelectFunction.NAME)
|
||||||
private Integer areaId;
|
private Integer areaId;
|
||||||
|
|
||||||
@ExcelProperty("详细地址")
|
@ExcelProperty("详细地址")
|
||||||
|
@ -31,7 +31,7 @@ public class CrmCustomerTransferReqVO {
|
|||||||
private Integer oldOwnerPermissionLevel;
|
private Integer oldOwnerPermissionLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择
|
* 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择。选中时,也一起转移
|
||||||
*/
|
*/
|
||||||
@Schema(description = "同时转移", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
@Schema(description = "同时转移", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||||
private List<Integer> toBizTypes;
|
private List<Integer> toBizTypes;
|
||||||
|
@ -68,22 +68,24 @@ public class CrmPermissionController {
|
|||||||
@Resource
|
@Resource
|
||||||
private PostApi postApi;
|
private PostApi postApi;
|
||||||
|
|
||||||
|
// TODO @puhui999:是不是还是叫 create 好点哈。
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "创建数据权限")
|
@Operation(summary = "创建数据权限")
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@PreAuthorize("@ss.hasPermission('crm:permission:create')")
|
@PreAuthorize("@ss.hasPermission('crm:permission:create')")
|
||||||
@CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER)
|
@CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER)
|
||||||
public CommonResult<Boolean> addPermission(@Valid @RequestBody CrmPermissionSaveReqVO reqVO) {
|
public CommonResult<Boolean> savePermission(@Valid @RequestBody CrmPermissionSaveReqVO reqVO) {
|
||||||
permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class));
|
permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class));
|
||||||
|
// 处理【同时添加至】的权限
|
||||||
if (CollUtil.isNotEmpty(reqVO.getToBizTypes())) {
|
if (CollUtil.isNotEmpty(reqVO.getToBizTypes())) {
|
||||||
createBizTypePermissions(reqVO);
|
createBizTypePermissions(reqVO);
|
||||||
}
|
}
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createBizTypePermissions(CrmPermissionSaveReqVO reqVO) {
|
private void createBizTypePermissions(CrmPermissionSaveReqVO reqVO) {
|
||||||
List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>();
|
List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>();
|
||||||
|
// TODO @puhui999:需要考虑,被添加人,是不是应该有对应的权限了;
|
||||||
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) {
|
if (reqVO.getToBizTypes().contains(CrmBizTypeEnum.CRM_CONTACT.getType())) {
|
||||||
List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getBizId(), getLoginUserId());
|
List<CrmContactDO> contactList = contactService.getContactListByCustomerIdOwnerUserId(reqVO.getBizId(), getLoginUserId());
|
||||||
contactList.forEach(item -> {
|
contactList.forEach(item -> {
|
||||||
|
@ -33,7 +33,8 @@ public class CrmPermissionSaveReqVO {
|
|||||||
private Integer level;
|
private Integer level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加客户团队成员时,需要额外有【联系人】【商机】【合同】的 checkbox 选择
|
* 添加客户团队成员时,需要额外有【联系人】【商机】【合同】的 checkbox 选择。
|
||||||
|
* 选中时,同时添加对应的权限
|
||||||
*/
|
*/
|
||||||
@Schema(description = "同时添加", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
@Schema(description = "同时添加", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||||
private List<Integer> toBizTypes;
|
private List<Integer> toBizTypes;
|
||||||
|
@ -74,6 +74,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default List<CrmContactDO> selectListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId) {
|
default List<CrmContactDO> selectListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId) {
|
||||||
|
// TODO @puhui999:父类有 selectList,查询 2 个字段的简化方法哈,可以用下
|
||||||
return selectList(new LambdaQueryWrapperX<CrmContactDO>()
|
return selectList(new LambdaQueryWrapperX<CrmContactDO>()
|
||||||
.eq(CrmContactDO::getCustomerId, customerId)
|
.eq(CrmContactDO::getCustomerId, customerId)
|
||||||
.eq(CrmContactDO::getOwnerUserId, ownerUserId));
|
.eq(CrmContactDO::getOwnerUserId, ownerUserId));
|
||||||
|
@ -99,4 +99,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> {
|
|||||||
return convertMap(result, obj -> (Long) obj.get("contract_id"), obj -> (BigDecimal) obj.get("total_price"));
|
return convertMap(result, obj -> (Long) obj.get("contract_id"), obj -> (BigDecimal) obj.get("total_price"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Long selectCountByContractId(Long contractId) {
|
||||||
|
return selectCount(CrmReceivableDO::getContractId, contractId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,12 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Excel 所属地区列下拉数据源获取接口实现类
|
* Excel 所属地区列下拉数据源获取接口实现类
|
||||||
*
|
*
|
||||||
|
* // TODO @puhui999:类名叫:地区下拉框数据源的 {@link ExcelColumnSelectFunction} 实现类,这样看起来会更简洁一点哈
|
||||||
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class AreaExcelColumnSelectFunctionImpl implements ExcelColumnSelectFunction {
|
public class AreaExcelColumnSelectFunction implements ExcelColumnSelectFunction {
|
||||||
|
|
||||||
public static final String NAME = "getCrmAreaNameList"; // 防止和别的模块重名
|
public static final String NAME = "getCrmAreaNameList"; // 防止和别的模块重名
|
||||||
|
|
@ -1 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* crm 模块的 excel 拓展封装
|
||||||
|
*/
|
||||||
package cn.iocoder.yudao.module.crm.framework.excel;
|
package cn.iocoder.yudao.module.crm.framework.excel;
|
@ -1 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* crm 模块的 operatelog 拓展封装
|
||||||
|
*/
|
||||||
package cn.iocoder.yudao.module.crm.framework.operatelog;
|
package cn.iocoder.yudao.module.crm.framework.operatelog;
|
@ -1 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* crm 模块的 permission 拓展封装
|
||||||
|
*/
|
||||||
package cn.iocoder.yudao.module.crm.framework.permission;
|
package cn.iocoder.yudao.module.crm.framework.permission;
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* trade 模块的 web 配置
|
* crm 模块的 web 拓展封装
|
||||||
*/
|
*/
|
||||||
package cn.iocoder.yudao.module.crm.framework.web;
|
package cn.iocoder.yudao.module.crm.framework.web;
|
||||||
|
@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.collection.ListUtil;
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
@ -27,7 +26,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
|
|||||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
||||||
import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
|
import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
|
||||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerServiceImpl;
|
|
||||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
||||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||||
@ -231,7 +229,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||||||
// 1.1 校验存在
|
// 1.1 校验存在
|
||||||
CrmContractDO contract = validateContractExists(id);
|
CrmContractDO contract = validateContractExists(id);
|
||||||
// 1.2 如果被 CrmReceivableDO 所使用,则不允许删除
|
// 1.2 如果被 CrmReceivableDO 所使用,则不允许删除
|
||||||
if (receivableService.getReceivableByContractId(contract.getId()) != 0) {
|
if (receivableService.getReceivableCountByContractId(contract.getId()) > 0) {
|
||||||
throw exception(CONTRACT_DELETE_FAIL);
|
throw exception(CONTRACT_DELETE_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +123,11 @@ public interface CrmReceivableService {
|
|||||||
Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds);
|
Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更具合同编号查询回款列表
|
* 根据合同编号查询回款数量
|
||||||
*
|
*
|
||||||
* @param contractId 合同编号
|
* @param contractId 合同编号
|
||||||
* @return 回款
|
* @return 回款数量
|
||||||
*/
|
*/
|
||||||
Long getReceivableByContractId(Long contractId);
|
Long getReceivableCountByContractId(Long contractId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -302,8 +302,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getReceivableByContractId(Long contractId) {
|
public Long getReceivableCountByContractId(Long contractId) {
|
||||||
return receivableMapper.selectCount(CrmReceivableDO::getContractId, contractId);
|
return receivableMapper.selectCountByContractId(contractId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user