Commit c4ff0a103816be47c97d471267e3337eb9909c94

Authored by puhui999
2 parents dc695e3c b285548b

Merge remote-tracking branch 'yudao/develop' into develop

Showing 12 changed files with 76 additions and 51 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -39,6 +39,7 @@ public interface ErrorCodeConstants { @@ -39,6 +39,7 @@ public interface ErrorCodeConstants {
39 ErrorCode RECEIVABLE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_004_004, "更新回款审核状态失败,原因:回款不是审核中状态"); 39 ErrorCode RECEIVABLE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_004_004, "更新回款审核状态失败,原因:回款不是审核中状态");
40 ErrorCode RECEIVABLE_NO_EXISTS = new ErrorCode(1_020_004_005, "生成回款序列号重复,请重试"); 40 ErrorCode RECEIVABLE_NO_EXISTS = new ErrorCode(1_020_004_005, "生成回款序列号重复,请重试");
41 ErrorCode RECEIVABLE_CREATE_FAIL_CONTRACT_NOT_APPROVE = new ErrorCode(1_020_004_006, "创建回款失败,原因:合同不是审核通过状态"); 41 ErrorCode RECEIVABLE_CREATE_FAIL_CONTRACT_NOT_APPROVE = new ErrorCode(1_020_004_006, "创建回款失败,原因:合同不是审核通过状态");
  42 + ErrorCode RECEIVABLE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT = new ErrorCode(1_020_004_007, "创建回款失败,原因:回款金额超出合同金额,目前剩余可退:{} 元");
42 43
43 // ========== 回款计划 1-020-005-000 ========== 44 // ========== 回款计划 1-020-005-000 ==========
44 ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); 45 ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在");
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
@@ -164,13 +164,6 @@ public class CrmReceivableController { @@ -164,13 +164,6 @@ public class CrmReceivableController {
164 }); 164 });
165 } 165 }
166 166
167 - @GetMapping("/check-receivables-count")  
168 - @Operation(summary = "获得待审核回款数量")  
169 - @PreAuthorize("@ss.hasPermission('crm:receivable:query')")  
170 - public CommonResult<Long> getCheckReceivablesCount() {  
171 - return success(receivableService.getCheckReceivablesCount(getLoginUserId()));  
172 - }  
173 -  
174 @PutMapping("/submit") 167 @PutMapping("/submit")
175 @Operation(summary = "提交回款审批") 168 @Operation(summary = "提交回款审批")
176 @PreAuthorize("@ss.hasPermission('crm:receivable:update')") 169 @PreAuthorize("@ss.hasPermission('crm:receivable:update')")
@@ -179,4 +172,11 @@ public class CrmReceivableController { @@ -179,4 +172,11 @@ public class CrmReceivableController {
179 return success(true); 172 return success(true);
180 } 173 }
181 174
  175 + @GetMapping("/audit-count")
  176 + @Operation(summary = "获得待审核回款数量")
  177 + @PreAuthorize("@ss.hasPermission('crm:receivable:query')")
  178 + public CommonResult<Long> getAuditReceivableCount() {
  179 + return success(receivableService.getAuditReceivableCount(getLoginUserId()));
  180 + }
  181 +
182 } 182 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java
@@ -163,13 +163,6 @@ public class CrmReceivablePlanController { @@ -163,13 +163,6 @@ public class CrmReceivablePlanController {
163 }); 163 });
164 } 164 }
165 165
166 - @GetMapping("/remind-receivable-plan-count")  
167 - @Operation(summary = "获得待回款提醒数量")  
168 - @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')")  
169 - public CommonResult<Long> getRemindReceivablesCount() {  
170 - return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId()));  
171 - }  
172 -  
173 @GetMapping("/simple-list") 166 @GetMapping("/simple-list")
174 @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项") 167 @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项")
175 @Parameters({ 168 @Parameters({
@@ -187,4 +180,11 @@ public class CrmReceivablePlanController { @@ -187,4 +180,11 @@ public class CrmReceivablePlanController {
187 .setPrice(receivablePlan.getPrice()).setReturnType(receivablePlan.getReturnType()))); 180 .setPrice(receivablePlan.getPrice()).setReturnType(receivablePlan.getReturnType())));
188 } 181 }
189 182
  183 + @GetMapping("/remind-count")
  184 + @Operation(summary = "获得待回款提醒数量")
  185 + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')")
  186 + public CommonResult<Long> getReceivablePlanRemindCount() {
  187 + return success(receivablePlanService.getReceivablePlanRemindCount(getLoginUserId()));
  188 + }
  189 +
190 } 190 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
@@ -68,16 +68,22 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; { @@ -68,16 +68,22 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; {
68 return selectJoinList(CrmReceivableDO.class, query); 68 return selectJoinList(CrmReceivableDO.class, query);
69 } 69 }
70 70
71 - default Long selectCheckReceivablesCount(Long userId) { 71 + default Long selectCountByAudit(Long userId) {
72 MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); 72 MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
73 // 我负责的 + 非公海 73 // 我负责的 + 非公海
74 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), 74 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
75 CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 75 CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
76 - // 未提交 or 审核不通过  
77 - query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); 76 + // 未审核
  77 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.PROCESS.getStatus());
78 return selectCount(query); 78 return selectCount(query);
79 } 79 }
80 80
  81 + default List<CrmReceivableDO> selectListByContractIdAndStatus(Long contractId, Collection<Integer> auditStatuses) {
  82 + return selectList(new LambdaQueryWrapperX<CrmReceivableDO>()
  83 + .eq(CrmReceivableDO::getContractId, contractId)
  84 + .in(CrmReceivableDO::getAuditStatus, auditStatuses));
  85 + }
  86 +
81 default Map<Long, BigDecimal> selectReceivablePriceMapByContractId(Collection<Long> contractIds) { 87 default Map<Long, BigDecimal> selectReceivablePriceMapByContractId(Collection<Long> contractIds) {
82 if (CollUtil.isEmpty(contractIds)) { 88 if (CollUtil.isEmpty(contractIds)) {
83 return Collections.emptyMap(); 89 return Collections.emptyMap();
@@ -85,7 +91,8 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; { @@ -85,7 +91,8 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; {
85 // SQL sum 查询 91 // SQL sum 查询
86 List<Map<String, Object>> result = selectMaps(new QueryWrapper<CrmReceivableDO>() 92 List<Map<String, Object>> result = selectMaps(new QueryWrapper<CrmReceivableDO>()
87 .select("contract_id, SUM(price) AS total_price") 93 .select("contract_id, SUM(price) AS total_price")
88 - .eq("audit_status", CrmAuditStatusEnum.APPROVE.getStatus()) 94 + .in("audit_status", CrmAuditStatusEnum.DRAFT.getStatus(), // 草稿 + 审批中 + 审批通过
  95 + CrmAuditStatusEnum.PROCESS, CrmAuditStatusEnum.APPROVE.getStatus())
89 .groupBy("contract_id") 96 .groupBy("contract_id")
90 .in("contract_id", contractIds)); 97 .in("contract_id", contractIds));
91 // 获得金额 98 // 获得金额
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
@@ -60,19 +60,16 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -60,19 +60,16 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
60 } 60 }
61 61
62 // Backlog: 回款提醒类型 62 // Backlog: 回款提醒类型
63 - // TODO: @dhb52 需要配置 提前提醒天数  
64 - int REMIND_DAYS = 20;  
65 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 63 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
66 - LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());  
67 if (CrmReceivablePlanPageReqVO.REMIND_TYPE_NEEDED.equals(pageReqVO.getRemindType())) { // 待回款 64 if (CrmReceivablePlanPageReqVO.REMIND_TYPE_NEEDED.equals(pageReqVO.getRemindType())) { // 待回款
68 - query.isNull(CrmReceivablePlanDO::getReceivableId)  
69 - .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); 65 + query.isNull(CrmReceivablePlanDO::getReceivableId) // 未回款
  66 + .lt(CrmReceivablePlanDO::getReturnTime, beginOfToday) // 已逾期
  67 + .lt(CrmReceivablePlanDO::getRemindTime, beginOfToday); // 今天开始提醒
70 } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_EXPIRED.equals(pageReqVO.getRemindType())) { // 已逾期 68 } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_EXPIRED.equals(pageReqVO.getRemindType())) { // 已逾期
71 - query.isNull(CrmReceivablePlanDO::getReceivableId)  
72 - .lt(CrmReceivablePlanDO::getReturnTime, endOfToday); 69 + query.isNull(CrmReceivablePlanDO::getReceivableId) // 未回款
  70 + .ge(CrmReceivablePlanDO::getReturnTime, beginOfToday); // 已逾期
73 } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款 71 } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款
74 - query.isNotNull(CrmReceivablePlanDO::getReceivableId)  
75 - .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); 72 + query.isNotNull(CrmReceivablePlanDO::getReceivableId);
76 } 73 }
77 return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); 74 return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query);
78 } 75 }
@@ -86,20 +83,16 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -86,20 +83,16 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
86 return selectJoinList(CrmReceivablePlanDO.class, query); 83 return selectJoinList(CrmReceivablePlanDO.class, query);
87 } 84 }
88 85
89 - default Long selectRemindReceivablePlanCount(Long userId) { 86 + default Long selectReceivablePlanCountByRemind(Long userId) {
90 MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); 87 MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
91 // 我负责的 + 非公海 88 // 我负责的 + 非公海
92 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), 89 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
93 CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 90 CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
94 - // TODO: @dhb52 需要配置 提前提醒天数  
95 - int REMIND_DAYS = 20; 91 + // 未回款 + 已逾期 + 今天开始提醒
96 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 92 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
97 - LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());  
98 - query.isNull(CrmReceivablePlanDO::getReceivableId)  
99 - .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS));  
100 - // TODO return_time 小于现在;  
101 - // TODO 未回款  
102 - // TODO remind_time 大于现在; 93 + query.isNull(CrmReceivablePlanDO::getReceivableId) // 未回款
  94 + .lt(CrmReceivablePlanDO::getReturnTime, beginOfToday) // 已逾期
  95 + .lt(CrmReceivablePlanDO::getRemindTime, beginOfToday); // 今天开始提醒
103 return selectCount(query); 96 return selectCount(query);
104 } 97 }
105 98
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
1 /** 1 /**
2 - * TODO 芋艿:临时占位,后续可删除 2 + * 定时任务
3 */ 3 */
4 package cn.iocoder.yudao.module.crm.job; 4 package cn.iocoder.yudao.module.crm.job;
5 \ No newline at end of file 5 \ No newline at end of file
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -222,7 +222,7 @@ public class CrmContractServiceImpl implements CrmContractService { @@ -222,7 +222,7 @@ public class CrmContractServiceImpl implements CrmContractService {
222 success = CRM_CONTRACT_DELETE_SUCCESS) 222 success = CRM_CONTRACT_DELETE_SUCCESS)
223 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) 223 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
224 public void deleteContract(Long id) { 224 public void deleteContract(Long id) {
225 - // TODO @合同待定:如果被 CrmReceivableDO 所使用,则不允许删除 225 + // TODO @puhui999:如果被 CrmReceivableDO 所使用,则不允许删除
226 // 校验存在 226 // 校验存在
227 CrmContractDO contract = validateContractExists(id); 227 CrmContractDO contract = validateContractExists(id);
228 // 删除 228 // 删除
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
@@ -170,7 +170,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { @@ -170,7 +170,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
170 throw exception(CRM_PERMISSION_DELETE_FAIL); 170 throw exception(CRM_PERMISSION_DELETE_FAIL);
171 } 171 }
172 // 校验操作人是否为负责人 172 // 校验操作人是否为负责人
173 - CrmPermissionDO permission = permissionMapper.selectByBizIdAndUserId(permissions.getFirst().getBizId(), userId); 173 + CrmPermissionDO permission = permissionMapper.selectByBizIdAndUserId(permissions.get(0).getBizId(), userId);
174 if (permission == null) { 174 if (permission == null) {
175 throw exception(CRM_PERMISSION_DELETE_DENIED); 175 throw exception(CRM_PERMISSION_DELETE_DENIED);
176 } 176 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
@@ -90,6 +90,6 @@ public interface CrmReceivablePlanService { @@ -90,6 +90,6 @@ public interface CrmReceivablePlanService {
90 * @param userId 用户编号 90 * @param userId 用户编号
91 * @return 提醒数量 91 * @return 提醒数量
92 */ 92 */
93 - Long getRemindReceivablePlanCount(Long userId); 93 + Long getReceivablePlanRemindCount(Long userId);
94 94
95 } 95 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
@@ -184,8 +184,8 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @@ -184,8 +184,8 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
184 } 184 }
185 185
186 @Override 186 @Override
187 - public Long getRemindReceivablePlanCount(Long userId) {  
188 - return receivablePlanMapper.selectRemindReceivablePlanCount(userId); 187 + public Long getReceivablePlanRemindCount(Long userId) {
  188 + return receivablePlanMapper.selectReceivablePlanCountByRemind(userId);
189 } 189 }
190 190
191 } 191 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
@@ -110,9 +110,9 @@ public interface CrmReceivableService { @@ -110,9 +110,9 @@ public interface CrmReceivableService {
110 * 获得待审核回款数量 110 * 获得待审核回款数量
111 * 111 *
112 * @param userId 用户编号 112 * @param userId 用户编号
113 - * @return 提醒数量 113 + * @return 待审批数量
114 */ 114 */
115 - Long getCheckReceivablesCount(Long userId); 115 + Long getAuditReceivableCount(Long userId);
116 116
117 /** 117 /**
118 * 获得合同已回款金额 Map 118 * 获得合同已回款金额 Map
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
@@ -6,6 +6,7 @@ import cn.hutool.core.lang.Assert; @@ -6,6 +6,7 @@ import cn.hutool.core.lang.Assert;
6 import cn.hutool.core.util.ObjUtil; 6 import cn.hutool.core.util.ObjUtil;
7 import cn.hutool.core.util.ObjectUtil; 7 import cn.hutool.core.util.ObjectUtil;
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 10 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
11 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; 12 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
@@ -36,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional; @@ -36,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
36 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
37 38
38 import java.math.BigDecimal; 39 import java.math.BigDecimal;
  40 +import java.util.Arrays;
39 import java.util.Collection; 41 import java.util.Collection;
40 import java.util.List; 42 import java.util.List;
41 import java.util.Map; 43 import java.util.Map;
@@ -85,18 +87,21 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -85,18 +87,21 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
85 @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}", 87 @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}",
86 success = CRM_RECEIVABLE_CREATE_SUCCESS) 88 success = CRM_RECEIVABLE_CREATE_SUCCESS)
87 public Long createReceivable(CrmReceivableSaveReqVO createReqVO) { 89 public Long createReceivable(CrmReceivableSaveReqVO createReqVO) {
88 - // 1.1 校验关联数据存在 90 + // 1.1 校验可回款金额超过上限
  91 + validateReceivablePriceExceedsLimit(createReqVO);
  92 + // 1.2 校验关联数据存在
89 validateRelationDataExists(createReqVO); 93 validateRelationDataExists(createReqVO);
90 - // 1.2 生成回款编号 94 + // 1.3 生成回款编号
91 String no = noRedisDAO.generate(CrmNoRedisDAO.RECEIVABLE_PREFIX); 95 String no = noRedisDAO.generate(CrmNoRedisDAO.RECEIVABLE_PREFIX);
92 if (receivableMapper.selectByNo(no) != null) { 96 if (receivableMapper.selectByNo(no) != null) {
93 throw exception(RECEIVABLE_NO_EXISTS); 97 throw exception(RECEIVABLE_NO_EXISTS);
94 } 98 }
95 99
96 - // 2. 插入回款 100 + // 2.1 插入回款
97 CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class) 101 CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class)
98 .setNo(no).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); 102 .setNo(no).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus());
99 receivableMapper.insert(receivable); 103 receivableMapper.insert(receivable);
  104 + // 2.2
100 105
101 // 3. 创建数据权限 106 // 3. 创建数据权限
102 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()) 107 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType())
@@ -113,6 +118,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -113,6 +118,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
113 return receivable.getId(); 118 return receivable.getId();
114 } 119 }
115 120
  121 + private void validateReceivablePriceExceedsLimit(CrmReceivableSaveReqVO reqVO) {
  122 + // 1. 计算剩余可退款金额,不包括 reqVO 自身
  123 + CrmContractDO contract = contractService.validateContract(reqVO.getContractId());
  124 + List<CrmReceivableDO> receivables = receivableMapper.selectListByContractIdAndStatus(reqVO.getContractId(),
  125 + Arrays.asList(CrmAuditStatusEnum.APPROVE.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus()));
  126 + if (reqVO.getId() != null) {
  127 + receivables.removeIf(receivable -> ObjectUtil.equal(receivable.getId(), reqVO.getId()));
  128 + }
  129 + BigDecimal notReceivablePrice = contract.getTotalPrice().subtract(
  130 + CollectionUtils.getSumValue(receivables, CrmReceivableDO::getPrice, BigDecimal::add, BigDecimal.ZERO));
  131 + // 2. 校验金额是否超过
  132 + if (reqVO.getPrice().compareTo(notReceivablePrice) > 0) {
  133 + throw exception(RECEIVABLE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT, notReceivablePrice);
  134 + }
  135 + }
  136 +
116 private void validateRelationDataExists(CrmReceivableSaveReqVO reqVO) { 137 private void validateRelationDataExists(CrmReceivableSaveReqVO reqVO) {
117 if (reqVO.getOwnerUserId() != null) { 138 if (reqVO.getOwnerUserId() != null) {
118 adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 139 adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在
@@ -144,9 +165,11 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -144,9 +165,11 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
144 public void updateReceivable(CrmReceivableSaveReqVO updateReqVO) { 165 public void updateReceivable(CrmReceivableSaveReqVO updateReqVO) {
145 Assert.notNull(updateReqVO.getId(), "回款编号不能为空"); 166 Assert.notNull(updateReqVO.getId(), "回款编号不能为空");
146 updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段 167 updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段
147 - // 1.1 校验存在 168 + // 1.1 校验可回款金额超过上限
  169 + validateReceivablePriceExceedsLimit(updateReqVO);
  170 + // 1.2 校验存在
148 CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId()); 171 CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId());
149 - // 1.2 只有草稿、审批中,可以编辑; 172 + // 1.3 只有草稿、审批中,可以编辑;
150 if (!ObjectUtils.equalsAny(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), 173 if (!ObjectUtils.equalsAny(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
151 CrmAuditStatusEnum.PROCESS.getStatus())) { 174 CrmAuditStatusEnum.PROCESS.getStatus())) {
152 throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); 175 throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED);
@@ -189,6 +212,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -189,6 +212,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
189 if (receivable.getPlanId() != null && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) { 212 if (receivable.getPlanId() != null && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) {
190 throw exception(RECEIVABLE_DELETE_FAIL); 213 throw exception(RECEIVABLE_DELETE_FAIL);
191 } 214 }
  215 + // TODO @puhui999:审批通过时,不允许删除;
192 216
193 // 2. 删除 217 // 2. 删除
194 receivableMapper.deleteById(id); 218 receivableMapper.deleteById(id);
@@ -256,8 +280,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @@ -256,8 +280,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
256 } 280 }
257 281
258 @Override 282 @Override
259 - public Long getCheckReceivablesCount(Long userId) {  
260 - return receivableMapper.selectCheckReceivablesCount(userId); 283 + public Long getAuditReceivableCount(Long userId) {
  284 + return receivableMapper.selectCountByAudit(userId);
261 } 285 }
262 286
263 @Override 287 @Override