CRM-回款计划:添加数据权限

This commit is contained in:
puhui999 2023-12-11 15:56:12 +08:00
parent e4d3175f06
commit 1ac68aca97
8 changed files with 104 additions and 65 deletions

View File

@ -23,7 +23,8 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
CRM_BUSINESS(4, "商机"),
CRM_CONTRACT(5, "合同"),
CRM_PRODUCT(6, "产品"),
CRM_RECEIVABLE(7, "回款")
CRM_RECEIVABLE(7, "回款"),
CRM_RECEIVABLE_PLAN(8, "回款计划")
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();

View File

@ -38,6 +38,7 @@ import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@ -65,7 +66,7 @@ public class CrmReceivablePlanController {
@Operation(summary = "创建回款计划")
@PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')")
public CommonResult<Long> createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) {
return success(receivablePlanService.createReceivablePlan(createReqVO));
return success(receivablePlanService.createReceivablePlan(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@ -98,7 +99,7 @@ public class CrmReceivablePlanController {
@Operation(summary = "获得回款计划分页")
@PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')")
public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) {
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO);
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId());
return success(convertDetailReceivablePlanPage(pageResult));
}
@ -106,7 +107,7 @@ public class CrmReceivablePlanController {
@Operation(summary = "获得回款计划分页,基于指定客户")
public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) {
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomer(pageReqVO);
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO);
return success(convertDetailReceivablePlanPage(pageResult));
}
@ -117,7 +118,8 @@ public class CrmReceivablePlanController {
@OperateLog(type = EXPORT)
public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO,
HttpServletResponse response) throws IOException {
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO);
exportReqVO.setPageSize(PAGE_SIZE_NONE);
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId());
// 导出 Excel
ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class,
convertDetailReceivablePlanPage(pageResult).getList());

View File

@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 回款计划 Mapper
*
@ -15,18 +22,37 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> {
default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>()
.eqIfPresent(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId())
.eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId())
.orderByDesc(CrmReceivablePlanDO::getId));
default int updateOwnerUserIdById(Long id, Long ownerUserId) {
return update(new LambdaUpdateWrapper<CrmReceivablePlanDO>()
.eq(CrmReceivablePlanDO::getId, id)
.set(CrmReceivablePlanDO::getOwnerUserId, ownerUserId));
}
default PageResult<CrmReceivablePlanDO> selectPageByCustomer(CrmReceivablePlanPageReqVO reqVO) {
default PageResult<CrmReceivablePlanDO> selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>()
.eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递
.eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId())
.orderByDesc(CrmReceivablePlanDO::getId));
}
default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) {
MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
// 拼接数据权限的查询条件
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId,
userId, pageReqVO.getSceneType(), Boolean.FALSE);
// 拼接自身的查询条件
query.selectAll(CrmReceivablePlanDO.class)
.eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId())
.eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId())
.orderByDesc(CrmReceivablePlanDO::getId);
return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query);
}
default List<CrmReceivablePlanDO> selectBatchIds(Collection<Long> ids, Long userId) {
MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
// 拼接数据权限的查询条件
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId);
return selectJoinList(CrmReceivablePlanDO.class, query);
}
}

View File

@ -138,6 +138,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deletePermission(Integer bizType, Long bizId) {
// 删除数据权限
int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId);

View File

@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
import jakarta.validation.Valid;
import java.util.Collection;
import java.util.List;
@ -24,7 +24,7 @@ public interface CrmReceivablePlanService {
* @param createReqVO 创建信息
* @return 编号
*/
Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO);
Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO, Long userId);
/**
* 更新回款计划
@ -62,9 +62,10 @@ public interface CrmReceivablePlanService {
* 数据权限基于 {@link CrmReceivablePlanDO} 读取
*
* @param pageReqVO 分页查询
* @param userId 用户编号
* @return 回款计划分页
*/
PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO);
PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId);
/**
* 获得回款计划分页基于指定客户
@ -74,6 +75,6 @@ public interface CrmReceivablePlanService {
* @param pageReqVO 分页查询
* @return 回款计划分页
*/
PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO);
PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
}

View File

@ -17,10 +17,12 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.List;
@ -28,7 +30,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
// TODO @liuhongfeng参考 CrmReceivableServiceImpl 写的 todo
// TODO @puhui999数据权限
/**
* 回款计划 Service 实现类
*
@ -45,9 +47,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
private CrmContractService contractService;
@Resource
private CrmCustomerService customerService;
@Resource
private CrmPermissionService crmPermissionService;
@Override
public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO) {
public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) {
// 插入
CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO);
receivablePlan.setFinishStatus(false);
@ -55,29 +59,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
checkReceivablePlan(receivablePlan);
receivablePlanMapper.insert(receivablePlan);
// 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType())
.setBizId(receivablePlan.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
// 返回
return receivablePlan.getId();
}
private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) {
if(ObjectUtil.isNull(receivablePlan.getContractId())){
if (ObjectUtil.isNull(receivablePlan.getContractId())) {
throw exception(CONTRACT_NOT_EXISTS);
}
CrmContractDO contract = contractService.getContract(receivablePlan.getContractId());
if(ObjectUtil.isNull(contract)){
if (ObjectUtil.isNull(contract)) {
throw exception(CONTRACT_NOT_EXISTS);
}
CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId());
if(ObjectUtil.isNull(customer)){
if (ObjectUtil.isNull(customer)) {
throw exception(CUSTOMER_NOT_EXISTS);
}
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) {
// 校验存在
validateReceivablePlanExists(updateReqVO.getId());
@ -88,6 +96,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
public void deleteReceivablePlan(Long id) {
// 校验存在
validateReceivablePlanExists(id);
@ -102,6 +111,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.READ)
public CrmReceivablePlanDO getReceivablePlan(Long id) {
return receivablePlanMapper.selectById(id);
}
@ -115,14 +125,14 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
}
@Override
public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO) {
return receivablePlanMapper.selectPage(pageReqVO);
public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) {
return receivablePlanMapper.selectPage(pageReqVO, userId);
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ)
public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO) {
return receivablePlanMapper.selectPageByCustomer(pageReqVO);
public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO) {
return receivablePlanMapper.selectPageByCustomerId(pageReqVO);
}
}

View File

@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
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
import static org.junit.jupiter.api.Assertions.*;
// TODO 芋艿后续需要补充测试用例
/**
* {@link CrmReceivablePlanServiceImpl} 的单元测试类
*
@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class);
// 调用
Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO);
Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO, 1L);
// 断言
assertNotNull(receivablePlanId);
// 校验记录的属性是否正确
@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
// 调用
receivablePlanService.deleteReceivablePlan(id);
// 校验数据不存在了
assertNull(crmReceivablePlanMapper.selectById(id));
// 校验数据不存在了
assertNull(crmReceivablePlanMapper.selectById(id));
}
@Test
@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetReceivablePlanPage() {
// mock 数据
CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到
o.setPeriod(null);
o.setReturnTime(null);
o.setRemindDays(null);
o.setRemindTime(null);
o.setCustomerId(null);
o.setContractId(null);
o.setOwnerUserId(null);
o.setRemark(null);
o.setCreateTime(null);
});
crmReceivablePlanMapper.insert(dbReceivablePlan);
// 测试 customerId 不匹配
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null)));
// 测试 contractId 不匹配
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null)));
// 准备参数
CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO();
reqVO.setCustomerId(null);
reqVO.setContractId(null);
// 调用
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0));
// mock 数据
CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到
o.setPeriod(null);
o.setReturnTime(null);
o.setRemindDays(null);
o.setRemindTime(null);
o.setCustomerId(null);
o.setContractId(null);
o.setOwnerUserId(null);
o.setRemark(null);
o.setCreateTime(null);
});
crmReceivablePlanMapper.insert(dbReceivablePlan);
// 测试 customerId 不匹配
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null)));
// 测试 contractId 不匹配
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null)));
// 准备参数
CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO();
reqVO.setCustomerId(null);
reqVO.setContractId(null);
reqVO.setPageSize(PAGE_SIZE_NONE);
// 调用
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO, 1L);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0));
}
}

View File

@ -63,7 +63,7 @@ export function export${simpleClassName}Excel(params) {
responseType: 'blob'
})
}
## 特殊:主子表专属逻辑 TODO @puhui999下面方法的【空格】不太对
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) {
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
#if ($table.templateType == 11)
// 获得${subTable.classComment}分页
export function get${subSimpleClassName}Page(params) {
return request({
@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) {
}
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
#if ($subTable.subJoinMany)
// 获得${subTable.classComment}列表
export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) {
return request({
@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) {
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
#if ($table.templateType == 11)
// 新增${subTable.classComment}
export function create${subSimpleClassName}(data) {
return request({
@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) {
data
})
}
// 修改${subTable.classComment}
export function update${subSimpleClassName}(data) {
return request({
@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) {
data
})
}
// 删除${subTable.classComment}
export function delete${subSimpleClassName}(id) {
return request({
@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) {
method: 'delete'
})
}
// 获得${subTable.classComment}
export function get${subSimpleClassName}(id) {
return request({