Commit dc695e3cdab93073ec4f2459a87b9d63395815ef
Merge remote-tracking branch 'yudao/develop' into develop
Showing
29 changed files
with
465 additions
and
313 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
| @@ -14,5 +14,6 @@ public interface DictTypeConstants { | @@ -14,5 +14,6 @@ public interface DictTypeConstants { | ||
| 14 | String CRM_PRODUCT_UNIT = "crm_product_unit"; // CRM 产品单位 | 14 | String CRM_PRODUCT_UNIT = "crm_product_unit"; // CRM 产品单位 |
| 15 | String CRM_PRODUCT_STATUS = "crm_product_status"; // CRM 产品状态 | 15 | String CRM_PRODUCT_STATUS = "crm_product_status"; // CRM 产品状态 |
| 16 | String CRM_FOLLOW_UP_TYPE = "crm_follow_up_type"; // CRM 跟进方式 | 16 | String CRM_FOLLOW_UP_TYPE = "crm_follow_up_type"; // CRM 跟进方式 |
| 17 | + String CRM_RECEIVABLE_RETURN_TYPE = "crm_receivable_return_type"; // CRM 回款方式 | ||
| 17 | 18 | ||
| 18 | } | 19 | } |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
| @@ -28,7 +28,6 @@ public interface ErrorCodeConstants { | @@ -28,7 +28,6 @@ public interface ErrorCodeConstants { | ||
| 28 | 28 | ||
| 29 | // ========== 联系人管理 1-020-003-000 ========== | 29 | // ========== 联系人管理 1-020-003-000 ========== |
| 30 | ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); | 30 | ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); |
| 31 | - ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); | ||
| 32 | ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); | 31 | ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); |
| 33 | ErrorCode CONTACT_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_003_003, "更新联系人负责人失败"); | 32 | ErrorCode CONTACT_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_003_003, "更新联系人负责人失败"); |
| 34 | 33 | ||
| @@ -38,10 +37,13 @@ public interface ErrorCodeConstants { | @@ -38,10 +37,13 @@ public interface ErrorCodeConstants { | ||
| 38 | ErrorCode RECEIVABLE_DELETE_FAIL = new ErrorCode(1_020_004_002, "删除回款失败,原因: 被回款计划所使用,不允许删除"); | 37 | ErrorCode RECEIVABLE_DELETE_FAIL = new ErrorCode(1_020_004_002, "删除回款失败,原因: 被回款计划所使用,不允许删除"); |
| 39 | ErrorCode RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_004_003, "回款提交审核失败,原因:回款没处在未提交状态"); | 38 | ErrorCode RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_004_003, "回款提交审核失败,原因:回款没处在未提交状态"); |
| 40 | 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, "生成回款序列号重复,请重试"); | ||
| 41 | + ErrorCode RECEIVABLE_CREATE_FAIL_CONTRACT_NOT_APPROVE = new ErrorCode(1_020_004_006, "创建回款失败,原因:合同不是审核通过状态"); | ||
| 41 | 42 | ||
| 42 | // ========== 回款计划 1-020-005-000 ========== | 43 | // ========== 回款计划 1-020-005-000 ========== |
| 43 | ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); | 44 | ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); |
| 44 | - ErrorCode RECEIVABLE_PLAN_UPDATE_FAIL = new ErrorCode(1_020_006_000, "更想回款计划失败,原因:{}"); | 45 | + ErrorCode RECEIVABLE_PLAN_UPDATE_FAIL = new ErrorCode(1_020_006_000, "更想回款计划失败,原因:已经有对应的还款"); |
| 46 | + ErrorCode RECEIVABLE_PLAN_EXISTS_RECEIVABLE = new ErrorCode(1_020_006_001, "回款计划已经有对应的回款,不能使用"); | ||
| 45 | 47 | ||
| 46 | // ========== 客户管理 1_020_006_000 ========== | 48 | // ========== 客户管理 1_020_006_000 ========== |
| 47 | ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在"); | 49 | ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在"); |
| @@ -64,10 +66,8 @@ public interface ErrorCodeConstants { | @@ -64,10 +66,8 @@ public interface ErrorCodeConstants { | ||
| 64 | // ========== 权限管理 1_020_007_000 ========== | 66 | // ========== 权限管理 1_020_007_000 ========== |
| 65 | ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); | 67 | ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); |
| 66 | ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限"); | 68 | ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限"); |
| 67 | - ErrorCode CRM_PERMISSION_MODEL_NOT_EXISTS = new ErrorCode(1_020_007_002, "{}不存在"); | ||
| 68 | ErrorCode CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS = new ErrorCode(1_020_007_003, "{}操作失败,原因:转移对象已经是该负责人"); | 69 | ErrorCode CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS = new ErrorCode(1_020_007_003, "{}操作失败,原因:转移对象已经是该负责人"); |
| 69 | ErrorCode CRM_PERMISSION_DELETE_FAIL = new ErrorCode(1_020_007_004, "删除数据权限失败,原因:批量删除权限的时候,只能属于同一个 bizId 下"); | 70 | ErrorCode CRM_PERMISSION_DELETE_FAIL = new ErrorCode(1_020_007_004, "删除数据权限失败,原因:批量删除权限的时候,只能属于同一个 bizId 下"); |
| 70 | - ErrorCode CRM_PERMISSION_DELETE_FAIL_EXIST_OWNER = new ErrorCode(1_020_007_005, "删除数据权限失败,原因:存在负责人"); | ||
| 71 | ErrorCode CRM_PERMISSION_DELETE_DENIED = new ErrorCode(1_020_007_006, "删除数据权限失败,原因:没有权限"); | 71 | ErrorCode CRM_PERMISSION_DELETE_DENIED = new ErrorCode(1_020_007_006, "删除数据权限失败,原因:没有权限"); |
| 72 | ErrorCode CRM_PERMISSION_DELETE_SELF_PERMISSION_FAIL_EXIST_OWNER = new ErrorCode(1_020_007_007, "删除数据权限失败,原因:不能删除负责人"); | 72 | ErrorCode CRM_PERMISSION_DELETE_SELF_PERMISSION_FAIL_EXIST_OWNER = new ErrorCode(1_020_007_007, "删除数据权限失败,原因:不能删除负责人"); |
| 73 | ErrorCode CRM_PERMISSION_CREATE_FAIL = new ErrorCode(1_020_007_008, "创建数据权限失败,原因:所加用户已有权限"); | 73 | ErrorCode CRM_PERMISSION_CREATE_FAIL = new ErrorCode(1_020_007_008, "创建数据权限失败,原因:所加用户已有权限"); |
| @@ -93,7 +93,6 @@ public interface ErrorCodeConstants { | @@ -93,7 +93,6 @@ public interface ErrorCodeConstants { | ||
| 93 | ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_010_003, "商机状态不存在"); | 93 | ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_010_003, "商机状态不存在"); |
| 94 | 94 | ||
| 95 | // ========== 客户公海规则设置 1_020_012_000 ========== | 95 | // ========== 客户公海规则设置 1_020_012_000 ========== |
| 96 | - ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); | ||
| 97 | ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_001, "客户限制配置不存在"); | 96 | ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_001, "客户限制配置不存在"); |
| 98 | 97 | ||
| 99 | // ========== 跟进记录 1_020_013_000 ========== | 98 | // ========== 跟进记录 1_020_013_000 ========== |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract; | ||
| 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.lang.Assert; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | 8 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 8 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | 9 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| @@ -24,6 +25,7 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | @@ -24,6 +25,7 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | ||
| 24 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 25 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 25 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 26 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 26 | import cn.iocoder.yudao.module.crm.service.product.CrmProductService; | 27 | import cn.iocoder.yudao.module.crm.service.product.CrmProductService; |
| 28 | +import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; | ||
| 27 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 29 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 28 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | 30 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 29 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 31 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -39,6 +41,7 @@ import org.springframework.validation.annotation.Validated; | @@ -39,6 +41,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 39 | import org.springframework.web.bind.annotation.*; | 41 | import org.springframework.web.bind.annotation.*; |
| 40 | 42 | ||
| 41 | import java.io.IOException; | 43 | import java.io.IOException; |
| 44 | +import java.math.BigDecimal; | ||
| 42 | import java.util.Collections; | 45 | import java.util.Collections; |
| 43 | import java.util.List; | 46 | import java.util.List; |
| 44 | import java.util.Map; | 47 | import java.util.Map; |
| @@ -67,6 +70,8 @@ public class CrmContractController { | @@ -67,6 +70,8 @@ public class CrmContractController { | ||
| 67 | private CrmBusinessService businessService; | 70 | private CrmBusinessService businessService; |
| 68 | @Resource | 71 | @Resource |
| 69 | private CrmProductService productService; | 72 | private CrmProductService productService; |
| 73 | + @Resource | ||
| 74 | + private CrmReceivableService receivableService; | ||
| 70 | 75 | ||
| 71 | @Resource | 76 | @Resource |
| 72 | private AdminUserApi adminUserApi; | 77 | private AdminUserApi adminUserApi; |
| @@ -174,12 +179,6 @@ public class CrmContractController { | @@ -174,12 +179,6 @@ public class CrmContractController { | ||
| 174 | return success(true); | 179 | return success(true); |
| 175 | } | 180 | } |
| 176 | 181 | ||
| 177 | - /** | ||
| 178 | - * 构建详细的合同结果 | ||
| 179 | - * | ||
| 180 | - * @param contractList 原始合同信息 | ||
| 181 | - * @return 细的合同结果 | ||
| 182 | - */ | ||
| 183 | private List<CrmContractRespVO> buildContractDetailList(List<CrmContractDO> contractList) { | 182 | private List<CrmContractRespVO> buildContractDetailList(List<CrmContractDO> contractList) { |
| 184 | if (CollUtil.isEmpty(contractList)) { | 183 | if (CollUtil.isEmpty(contractList)) { |
| 185 | return Collections.emptyList(); | 184 | return Collections.emptyList(); |
| @@ -197,6 +196,9 @@ public class CrmContractController { | @@ -197,6 +196,9 @@ public class CrmContractController { | ||
| 197 | // 1.4 获取商机 | 196 | // 1.4 获取商机 |
| 198 | Map<Long, CrmBusinessDO> businessMap = businessService.getBusinessMap( | 197 | Map<Long, CrmBusinessDO> businessMap = businessService.getBusinessMap( |
| 199 | convertSet(contractList, CrmContractDO::getBusinessId)); | 198 | convertSet(contractList, CrmContractDO::getBusinessId)); |
| 199 | + // 1.5 获得已回款金额 | ||
| 200 | + Map<Long, BigDecimal> receivablePriceMap = receivableService.getReceivablePriceMapByContractId( | ||
| 201 | + convertSet(contractList, CrmContractDO::getId)); | ||
| 200 | // 2. 拼接数据 | 202 | // 2. 拼接数据 |
| 201 | return BeanUtils.toBean(contractList, CrmContractRespVO.class, contractVO -> { | 203 | return BeanUtils.toBean(contractList, CrmContractRespVO.class, contractVO -> { |
| 202 | // 2.1 设置客户信息 | 204 | // 2.1 设置客户信息 |
| @@ -212,6 +214,8 @@ public class CrmContractController { | @@ -212,6 +214,8 @@ public class CrmContractController { | ||
| 212 | findAndThen(contactMap, contractVO.getSignContactId(), contact -> contractVO.setSignContactName(contact.getName())); | 214 | findAndThen(contactMap, contractVO.getSignContactId(), contact -> contractVO.setSignContactName(contact.getName())); |
| 213 | // 2.4 设置商机信息 | 215 | // 2.4 设置商机信息 |
| 214 | findAndThen(businessMap, contractVO.getBusinessId(), business -> contractVO.setBusinessName(business.getName())); | 216 | findAndThen(businessMap, contractVO.getBusinessId(), business -> contractVO.setBusinessName(business.getName())); |
| 217 | + // 2.5 设置已回款金额 | ||
| 218 | + contractVO.setTotalReceivablePrice(receivablePriceMap.getOrDefault(contractVO.getId(), BigDecimal.ZERO)); | ||
| 215 | }); | 219 | }); |
| 216 | } | 220 | } |
| 217 | 221 | ||
| @@ -229,13 +233,24 @@ public class CrmContractController { | @@ -229,13 +233,24 @@ public class CrmContractController { | ||
| 229 | return success(contractService.getRemindContractCount(getLoginUserId())); | 233 | return success(contractService.getRemindContractCount(getLoginUserId())); |
| 230 | } | 234 | } |
| 231 | 235 | ||
| 232 | - @GetMapping("/list-all-simple-by-customer") | ||
| 233 | - @Operation(summary = "获得合同精简列表", description = "只包含有读权限的客户的合同,主要用于前端的下拉选项") | 236 | + @GetMapping("/simple-list") |
| 237 | + @Operation(summary = "获得合同精简列表", description = "只包含的合同,主要用于前端的下拉选项") | ||
| 234 | @Parameter(name = "customerId", description = "客户编号", required = true) | 238 | @Parameter(name = "customerId", description = "客户编号", required = true) |
| 235 | @PreAuthorize("@ss.hasPermission('crm:contract:query')") | 239 | @PreAuthorize("@ss.hasPermission('crm:contract:query')") |
| 236 | - public CommonResult<List<CrmContractRespVO>> getListAllSimpleByCustomer(@RequestParam("customerId") Long customerId) { | ||
| 237 | - PageResult<CrmContractDO> result = contractService.getContractPageByCustomerId(new CrmContractPageReqVO().setCustomerId(customerId)); | ||
| 238 | - return success(BeanUtils.toBean(result.getList(), CrmContractRespVO.class)); | 240 | + public CommonResult<List<CrmContractRespVO>> getContractSimpleList(@RequestParam("customerId") Long customerId) { |
| 241 | + CrmContractPageReqVO pageReqVO = new CrmContractPageReqVO().setCustomerId(customerId); | ||
| 242 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); // 不分页 | ||
| 243 | + PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageReqVO); | ||
| 244 | + if (CollUtil.isEmpty(pageResult.getList())) { | ||
| 245 | + return success(Collections.emptyList()); | ||
| 246 | + } | ||
| 247 | + // 拼接数据 | ||
| 248 | + Map<Long, BigDecimal> receivablePriceMap = receivableService.getReceivablePriceMapByContractId( | ||
| 249 | + convertSet(pageResult.getList(), CrmContractDO::getId)); | ||
| 250 | + return success(convertList(pageResult.getList(), contract -> new CrmContractRespVO() // 只返回 id、name 等精简字段 | ||
| 251 | + .setId(contract.getId()).setName(contract.getName()).setAuditStatus(contract.getAuditStatus()) | ||
| 252 | + .setTotalPrice(contract.getTotalPrice()) | ||
| 253 | + .setTotalReceivablePrice(receivablePriceMap.getOrDefault(contract.getId(), BigDecimal.ZERO)))); | ||
| 239 | } | 254 | } |
| 240 | 255 | ||
| 241 | } | 256 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java
| @@ -88,6 +88,10 @@ public class CrmContractRespVO { | @@ -88,6 +88,10 @@ public class CrmContractRespVO { | ||
| 88 | @ExcelProperty("合同金额") | 88 | @ExcelProperty("合同金额") |
| 89 | private BigDecimal totalPrice; | 89 | private BigDecimal totalPrice; |
| 90 | 90 | ||
| 91 | + @Schema(description = "已回款金额", example = "5617") | ||
| 92 | + @ExcelProperty("已回款金额") | ||
| 93 | + private BigDecimal totalReceivablePrice; | ||
| 94 | + | ||
| 91 | @Schema(description = "客户签约人编号", example = "18546") | 95 | @Schema(description = "客户签约人编号", example = "18546") |
| 92 | private Long signContactId; | 96 | private Long signContactId; |
| 93 | @Schema(description = "客户签约人", example = "小豆") | 97 | @Schema(description = "客户签约人", example = "小豆") |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java
| @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 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.framework.common.util.object.BeanUtils; |
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; | 6 | import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogV2RespVO; | 7 | +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogRespVO; |
| 8 | import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; | 8 | import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; |
| 9 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 9 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 10 | import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | 10 | import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; |
| @@ -54,11 +54,11 @@ public class CrmOperateLogController { | @@ -54,11 +54,11 @@ public class CrmOperateLogController { | ||
| 54 | @GetMapping("/page") | 54 | @GetMapping("/page") |
| 55 | @Operation(summary = "获得操作日志") | 55 | @Operation(summary = "获得操作日志") |
| 56 | @PreAuthorize("@ss.hasPermission('crm:operate-log:query')") | 56 | @PreAuthorize("@ss.hasPermission('crm:operate-log:query')") |
| 57 | - public CommonResult<PageResult<CrmOperateLogV2RespVO>> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { | 57 | + public CommonResult<PageResult<CrmOperateLogRespVO>> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { |
| 58 | OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); | 58 | OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); |
| 59 | reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 | 59 | reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 |
| 60 | reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId()); | 60 | reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId()); |
| 61 | - return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogV2RespVO.class)); | 61 | + return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogRespVO.class)); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | } | 64 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java
| @@ -6,10 +6,10 @@ import lombok.Data; | @@ -6,10 +6,10 @@ import lombok.Data; | ||
| 6 | 6 | ||
| 7 | import java.time.LocalDateTime; | 7 | import java.time.LocalDateTime; |
| 8 | 8 | ||
| 9 | -@Schema(description = "管理后台 - CRM 跟进 Response VO") | 9 | +@Schema(description = "管理后台 - CRM 操作日志 Response VO") |
| 10 | @Data | 10 | @Data |
| 11 | @ExcelIgnoreUnannotated | 11 | @ExcelIgnoreUnannotated |
| 12 | -public class CrmOperateLogV2RespVO { | 12 | +public class CrmOperateLogRespVO { |
| 13 | 13 | ||
| 14 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | 14 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") |
| 15 | private Long id; | 15 | private Long id; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
| @@ -4,20 +4,23 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,20 +4,23 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.lang.Assert; | 4 | import cn.hutool.core.lang.Assert; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | 8 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 9 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 9 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 10 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 10 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 11 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 12 | +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; | ||
| 11 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; | 13 | 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; | 14 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; |
| 13 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; | 15 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; |
| 14 | -import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; | ||
| 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 18 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 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; |
| 20 | import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; | 21 | import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; |
| 22 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||
| 23 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 21 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 24 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 22 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 25 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 23 | import io.swagger.v3.oas.annotations.Operation; | 26 | import io.swagger.v3.oas.annotations.Operation; |
| @@ -31,14 +34,15 @@ import org.springframework.validation.annotation.Validated; | @@ -31,14 +34,15 @@ import org.springframework.validation.annotation.Validated; | ||
| 31 | import org.springframework.web.bind.annotation.*; | 34 | import org.springframework.web.bind.annotation.*; |
| 32 | 35 | ||
| 33 | import java.io.IOException; | 36 | import java.io.IOException; |
| 37 | +import java.util.Collections; | ||
| 34 | import java.util.List; | 38 | import java.util.List; |
| 35 | import java.util.Map; | 39 | import java.util.Map; |
| 36 | import java.util.stream.Stream; | 40 | import java.util.stream.Stream; |
| 37 | 41 | ||
| 38 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 42 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 39 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | 43 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 40 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | ||
| 41 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 44 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 45 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 42 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 46 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 43 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 47 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 44 | 48 | ||
| @@ -57,6 +61,8 @@ public class CrmReceivableController { | @@ -57,6 +61,8 @@ public class CrmReceivableController { | ||
| 57 | 61 | ||
| 58 | @Resource | 62 | @Resource |
| 59 | private AdminUserApi adminUserApi; | 63 | private AdminUserApi adminUserApi; |
| 64 | + @Resource | ||
| 65 | + private DeptApi deptApi; | ||
| 60 | 66 | ||
| 61 | @PostMapping("/create") | 67 | @PostMapping("/create") |
| 62 | @Operation(summary = "创建回款") | 68 | @Operation(summary = "创建回款") |
| @@ -88,7 +94,14 @@ public class CrmReceivableController { | @@ -88,7 +94,14 @@ public class CrmReceivableController { | ||
| 88 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") | 94 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") |
| 89 | public CommonResult<CrmReceivableRespVO> getReceivable(@RequestParam("id") Long id) { | 95 | public CommonResult<CrmReceivableRespVO> getReceivable(@RequestParam("id") Long id) { |
| 90 | CrmReceivableDO receivable = receivableService.getReceivable(id); | 96 | CrmReceivableDO receivable = receivableService.getReceivable(id); |
| 91 | - return success(BeanUtils.toBean(receivable, CrmReceivableRespVO.class)); | 97 | + return success(buildReceivableDetail(receivable)); |
| 98 | + } | ||
| 99 | + | ||
| 100 | + private CrmReceivableRespVO buildReceivableDetail(CrmReceivableDO receivable) { | ||
| 101 | + if (receivable == null) { | ||
| 102 | + return null; | ||
| 103 | + } | ||
| 104 | + return buildReceivableDetailList(Collections.singletonList(receivable)).get(0); | ||
| 92 | } | 105 | } |
| 93 | 106 | ||
| 94 | @GetMapping("/page") | 107 | @GetMapping("/page") |
| @@ -96,7 +109,7 @@ public class CrmReceivableController { | @@ -96,7 +109,7 @@ public class CrmReceivableController { | ||
| 96 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") | 109 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") |
| 97 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { | 110 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { |
| 98 | PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId()); | 111 | PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId()); |
| 99 | - return success(buildReceivableDetailPage(pageResult)); | 112 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); |
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | @GetMapping("/page-by-customer") | 115 | @GetMapping("/page-by-customer") |
| @@ -104,7 +117,7 @@ public class CrmReceivableController { | @@ -104,7 +117,7 @@ public class CrmReceivableController { | ||
| 104 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { | 117 | public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { |
| 105 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | 118 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 106 | PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); | 119 | PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); |
| 107 | - return success(buildReceivableDetailPage(pageResult)); | 120 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); |
| 108 | } | 121 | } |
| 109 | 122 | ||
| 110 | @GetMapping("/export-excel") | 123 | @GetMapping("/export-excel") |
| @@ -114,36 +127,43 @@ public class CrmReceivableController { | @@ -114,36 +127,43 @@ public class CrmReceivableController { | ||
| 114 | public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, | 127 | public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, |
| 115 | HttpServletResponse response) throws IOException { | 128 | HttpServletResponse response) throws IOException { |
| 116 | exportReqVO.setPageSize(PAGE_SIZE_NONE); | 129 | exportReqVO.setPageSize(PAGE_SIZE_NONE); |
| 117 | - PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId()); | 130 | + List<CrmReceivableDO> list = receivableService.getReceivablePage(exportReqVO, getLoginUserId()).getList(); |
| 118 | // 导出 Excel | 131 | // 导出 Excel |
| 119 | ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, | 132 | ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, |
| 120 | - buildReceivableDetailPage(pageResult).getList()); | 133 | + buildReceivableDetailList(list)); |
| 121 | } | 134 | } |
| 122 | 135 | ||
| 123 | - /** | ||
| 124 | - * 构建详细的回款分页结果 | ||
| 125 | - * | ||
| 126 | - * @param pageResult 简单的回款分页结果 | ||
| 127 | - * @return 详细的回款分页结果 | ||
| 128 | - */ | ||
| 129 | - private PageResult<CrmReceivableRespVO> buildReceivableDetailPage(PageResult<CrmReceivableDO> pageResult) { | ||
| 130 | - List<CrmReceivableDO> receivableList = pageResult.getList(); | 136 | + private List<CrmReceivableRespVO> buildReceivableDetailList(List<CrmReceivableDO> receivableList) { |
| 131 | if (CollUtil.isEmpty(receivableList)) { | 137 | if (CollUtil.isEmpty(receivableList)) { |
| 132 | - return PageResult.empty(pageResult.getTotal()); | 138 | + return Collections.emptyList(); |
| 133 | } | 139 | } |
| 134 | - // 1. 获取客户列表 | ||
| 135 | - List<CrmCustomerDO> customerList = customerService.getCustomerList( | 140 | + // 1.1 获取客户列表 |
| 141 | + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap( | ||
| 136 | convertSet(receivableList, CrmReceivableDO::getCustomerId)); | 142 | convertSet(receivableList, CrmReceivableDO::getCustomerId)); |
| 137 | - // 2. 获取创建人、负责人列表 | 143 | + // 1.2 获取创建人、负责人列表 |
| 138 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivableList, | 144 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivableList, |
| 139 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); | 145 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); |
| 140 | - // 3. 获得合同列表 | ||
| 141 | - List<CrmContractDO> contractList = contractService.getContractList( | 146 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); |
| 147 | + // 1.3 获得合同列表 | ||
| 148 | + Map<Long, CrmContractDO> contractMap = contractService.getContractMap( | ||
| 142 | convertSet(receivableList, CrmReceivableDO::getContractId)); | 149 | convertSet(receivableList, CrmReceivableDO::getContractId)); |
| 143 | - return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); | 150 | + // 2. 拼接结果 |
| 151 | + return BeanUtils.toBean(receivableList, CrmReceivableRespVO.class, (receivableVO) -> { | ||
| 152 | + // 2.1 拼接客户名称 | ||
| 153 | + findAndThen(customerMap, receivableVO.getCustomerId(), customer -> receivableVO.setCustomerName(customer.getName())); | ||
| 154 | + // 2.2 拼接负责人、创建人名称 | ||
| 155 | + MapUtils.findAndThen(userMap, NumberUtils.parseLong(receivableVO.getCreator()), | ||
| 156 | + user -> receivableVO.setCreatorName(user.getNickname())); | ||
| 157 | + MapUtils.findAndThen(userMap, receivableVO.getOwnerUserId(), user -> { | ||
| 158 | + receivableVO.setOwnerUserName(user.getNickname()); | ||
| 159 | + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> receivableVO.setOwnerUserDeptName(dept.getName())); | ||
| 160 | + }); | ||
| 161 | + // 2.3 拼接合同信息 | ||
| 162 | + findAndThen(contractMap, receivableVO.getContractId(), contract -> | ||
| 163 | + receivableVO.setContract(BeanUtils.toBean(contract, CrmContractRespVO.class))); | ||
| 164 | + }); | ||
| 144 | } | 165 | } |
| 145 | 166 | ||
| 146 | - | ||
| 147 | @GetMapping("/check-receivables-count") | 167 | @GetMapping("/check-receivables-count") |
| 148 | @Operation(summary = "获得待审核回款数量") | 168 | @Operation(summary = "获得待审核回款数量") |
| 149 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") | 169 | @PreAuthorize("@ss.hasPermission('crm:receivable:query')") |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java
| @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||
| 11 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; | 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; | 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.CrmReceivablePlanSaveReqVO; | 13 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; |
| 14 | -import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; | 14 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; |
| 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| @@ -34,14 +34,15 @@ import org.springframework.validation.annotation.Validated; | @@ -34,14 +34,15 @@ import org.springframework.validation.annotation.Validated; | ||
| 34 | import org.springframework.web.bind.annotation.*; | 34 | import org.springframework.web.bind.annotation.*; |
| 35 | 35 | ||
| 36 | import java.io.IOException; | 36 | import java.io.IOException; |
| 37 | +import java.util.Collections; | ||
| 37 | import java.util.List; | 38 | import java.util.List; |
| 38 | import java.util.Map; | 39 | import java.util.Map; |
| 39 | import java.util.stream.Stream; | 40 | import java.util.stream.Stream; |
| 40 | 41 | ||
| 41 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 42 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 42 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | 43 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 43 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | ||
| 44 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 44 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 45 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 45 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | 46 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 46 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 47 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 47 | 48 | ||
| @@ -93,7 +94,14 @@ public class CrmReceivablePlanController { | @@ -93,7 +94,14 @@ public class CrmReceivablePlanController { | ||
| 93 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | 94 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 94 | public CommonResult<CrmReceivablePlanRespVO> getReceivablePlan(@RequestParam("id") Long id) { | 95 | public CommonResult<CrmReceivablePlanRespVO> getReceivablePlan(@RequestParam("id") Long id) { |
| 95 | CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(id); | 96 | CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(id); |
| 96 | - return success(BeanUtils.toBean(receivablePlan, CrmReceivablePlanRespVO.class)); | 97 | + return success(buildReceivablePlanDetail(receivablePlan)); |
| 98 | + } | ||
| 99 | + | ||
| 100 | + private CrmReceivablePlanRespVO buildReceivablePlanDetail(CrmReceivablePlanDO receivablePlan) { | ||
| 101 | + if (receivablePlan == null) { | ||
| 102 | + return null; | ||
| 103 | + } | ||
| 104 | + return buildReceivableDetailList(Collections.singletonList(receivablePlan)).get(0); | ||
| 97 | } | 105 | } |
| 98 | 106 | ||
| 99 | @GetMapping("/page") | 107 | @GetMapping("/page") |
| @@ -101,7 +109,7 @@ public class CrmReceivablePlanController { | @@ -101,7 +109,7 @@ public class CrmReceivablePlanController { | ||
| 101 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | 109 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 102 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | 110 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 103 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); | 111 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); |
| 104 | - return success(convertDetailReceivablePlanPage(pageResult)); | 112 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); |
| 105 | } | 113 | } |
| 106 | 114 | ||
| 107 | @GetMapping("/page-by-customer") | 115 | @GetMapping("/page-by-customer") |
| @@ -109,10 +117,9 @@ public class CrmReceivablePlanController { | @@ -109,10 +117,9 @@ public class CrmReceivablePlanController { | ||
| 109 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | 117 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 110 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | 118 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 111 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); | 119 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); |
| 112 | - return success(convertDetailReceivablePlanPage(pageResult)); | 120 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); |
| 113 | } | 121 | } |
| 114 | 122 | ||
| 115 | - // TODO 芋艿:后面在优化导出 | ||
| 116 | @GetMapping("/export-excel") | 123 | @GetMapping("/export-excel") |
| 117 | @Operation(summary = "导出回款计划 Excel") | 124 | @Operation(summary = "导出回款计划 Excel") |
| 118 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") | 125 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") |
| @@ -120,39 +127,42 @@ public class CrmReceivablePlanController { | @@ -120,39 +127,42 @@ public class CrmReceivablePlanController { | ||
| 120 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, | 127 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, |
| 121 | HttpServletResponse response) throws IOException { | 128 | HttpServletResponse response) throws IOException { |
| 122 | exportReqVO.setPageSize(PAGE_SIZE_NONE); | 129 | exportReqVO.setPageSize(PAGE_SIZE_NONE); |
| 123 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()); | 130 | + List<CrmReceivablePlanDO> list = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()).getList(); |
| 124 | // 导出 Excel | 131 | // 导出 Excel |
| 125 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, | 132 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, |
| 126 | - convertDetailReceivablePlanPage(pageResult).getList()); | 133 | + buildReceivableDetailList(list)); |
| 127 | } | 134 | } |
| 128 | 135 | ||
| 129 | - /** | ||
| 130 | - * 构建详细的回款计划分页结果 | ||
| 131 | - * | ||
| 132 | - * @param pageResult 简单的回款计划分页结果 | ||
| 133 | - * @return 详细的回款计划分页结果 | ||
| 134 | - */ | ||
| 135 | - private PageResult<CrmReceivablePlanRespVO> convertDetailReceivablePlanPage(PageResult<CrmReceivablePlanDO> pageResult) { | ||
| 136 | - List<CrmReceivablePlanDO> receivablePlanList = pageResult.getList(); | 136 | + private List<CrmReceivablePlanRespVO> buildReceivableDetailList(List<CrmReceivablePlanDO> receivablePlanList) { |
| 137 | if (CollUtil.isEmpty(receivablePlanList)) { | 137 | if (CollUtil.isEmpty(receivablePlanList)) { |
| 138 | - return PageResult.empty(pageResult.getTotal()); | 138 | + return Collections.emptyList(); |
| 139 | } | 139 | } |
| 140 | - // 1. 获取客户列表 | ||
| 141 | - List<CrmCustomerDO> customerList = customerService.getCustomerList( | 140 | + // 1.1 获取客户 Map |
| 141 | + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap( | ||
| 142 | convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); | 142 | convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); |
| 143 | - // 2. 获取创建人、负责人列表 | 143 | + // 1.2 获取创建人、负责人列表 |
| 144 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList, | 144 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList, |
| 145 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); | 145 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); |
| 146 | - // 3. 获得合同列表 | ||
| 147 | - List<CrmContractDO> contractList = contractService.getContractList( | 146 | + // 1.3 获得合同 Map |
| 147 | + Map<Long, CrmContractDO> contractMap = contractService.getContractMap( | ||
| 148 | convertSet(receivablePlanList, CrmReceivablePlanDO::getContractId)); | 148 | convertSet(receivablePlanList, CrmReceivablePlanDO::getContractId)); |
| 149 | - // 4. 获得还款列表 | ||
| 150 | - List<CrmReceivableDO> receivableList = receivableService.getReceivableList( | 149 | + // 1.4 获得回款 Map |
| 150 | + Map<Long, CrmReceivableDO> receivableMap = receivableService.getReceivableMap( | ||
| 151 | convertSet(receivablePlanList, CrmReceivablePlanDO::getReceivableId)); | 151 | convertSet(receivablePlanList, CrmReceivablePlanDO::getReceivableId)); |
| 152 | - return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); | 152 | + // 2. 拼接数据 |
| 153 | + return BeanUtils.toBean(receivablePlanList, CrmReceivablePlanRespVO.class, (receivablePlanVO) -> { | ||
| 154 | + // 2.1 拼接客户信息 | ||
| 155 | + findAndThen(customerMap, receivablePlanVO.getCustomerId(), customer -> receivablePlanVO.setCustomerName(customer.getName())); | ||
| 156 | + // 2.2 拼接用户信息 | ||
| 157 | + findAndThen(userMap, receivablePlanVO.getOwnerUserId(), user -> receivablePlanVO.setOwnerUserName(user.getNickname())); | ||
| 158 | + findAndThen(userMap, Long.parseLong(receivablePlanVO.getCreator()), user -> receivablePlanVO.setCreatorName(user.getNickname())); | ||
| 159 | + // 2.3 拼接合同信息 | ||
| 160 | + findAndThen(contractMap, receivablePlanVO.getContractId(), contract -> receivablePlanVO.setContractNo(contract.getNo())); | ||
| 161 | + // 2.4 拼接回款信息 | ||
| 162 | + receivablePlanVO.setReceivable(BeanUtils.toBean(receivableMap.get(receivablePlanVO.getReceivableId()), CrmReceivableRespVO.class)); | ||
| 163 | + }); | ||
| 153 | } | 164 | } |
| 154 | 165 | ||
| 155 | - | ||
| 156 | @GetMapping("/remind-receivable-plan-count") | 166 | @GetMapping("/remind-receivable-plan-count") |
| 157 | @Operation(summary = "获得待回款提醒数量") | 167 | @Operation(summary = "获得待回款提醒数量") |
| 158 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | 168 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| @@ -160,18 +170,21 @@ public class CrmReceivablePlanController { | @@ -160,18 +170,21 @@ public class CrmReceivablePlanController { | ||
| 160 | return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId())); | 170 | return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId())); |
| 161 | } | 171 | } |
| 162 | 172 | ||
| 163 | - @GetMapping("/list-all-simple-by-customer") | 173 | + @GetMapping("/simple-list") |
| 164 | @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项") | 174 | @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项") |
| 165 | @Parameters({ | 175 | @Parameters({ |
| 166 | @Parameter(name = "customerId", description = "客户编号", required = true), | 176 | @Parameter(name = "customerId", description = "客户编号", required = true), |
| 167 | @Parameter(name = "contractId", description = "合同编号", required = true) | 177 | @Parameter(name = "contractId", description = "合同编号", required = true) |
| 168 | }) | 178 | }) |
| 169 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | 179 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 170 | - public CommonResult<List<CrmReceivablePlanRespVO>> getListAllSimpleByCustomer(@RequestParam("customerId") Long customerId, | ||
| 171 | - @RequestParam("contractId") Long contractId) { | ||
| 172 | - PageResult<CrmReceivablePlanDO> result = receivablePlanService.getReceivablePlanPageByCustomerId( | ||
| 173 | - new CrmReceivablePlanPageReqVO().setCustomerId(customerId).setContractId(contractId)); | ||
| 174 | - return success(BeanUtils.toBean(result.getList(), CrmReceivablePlanRespVO.class)); | 180 | + public CommonResult<List<CrmReceivablePlanRespVO>> getReceivablePlanSimpleList(@RequestParam("customerId") Long customerId, |
| 181 | + @RequestParam("contractId") Long contractId) { | ||
| 182 | + CrmReceivablePlanPageReqVO pageReqVO = new CrmReceivablePlanPageReqVO().setCustomerId(customerId).setContractId(contractId); | ||
| 183 | + pageReqVO.setPageNo(PAGE_SIZE_NONE); | ||
| 184 | + PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); | ||
| 185 | + return success(convertList(pageResult.getList(), receivablePlan -> new CrmReceivablePlanRespVO() // 只返回 id、period 等信息 | ||
| 186 | + .setId(receivablePlan.getId()).setPeriod(receivablePlan.getPeriod()).setReceivableId(receivablePlan.getReceivableId()) | ||
| 187 | + .setPrice(receivablePlan.getPrice()).setReturnType(receivablePlan.getReturnType()))); | ||
| 175 | } | 188 | } |
| 176 | 189 | ||
| 177 | } | 190 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java
| 1 | package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; | 1 | package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; | ||
| 4 | +import com.alibaba.excel.annotation.ExcelProperty; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 6 | import lombok.Data; |
| 5 | 7 | ||
| @@ -35,17 +37,16 @@ public class CrmReceivablePlanRespVO { | @@ -35,17 +37,16 @@ public class CrmReceivablePlanRespVO { | ||
| 35 | @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") | 37 | @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") |
| 36 | private LocalDateTime returnTime; | 38 | private LocalDateTime returnTime; |
| 37 | 39 | ||
| 38 | - @Schema(description = "回款方式", example = "1") | ||
| 39 | - private Integer returnType; // 来自 Receivable 的 returnType 字段 | 40 | + @Schema(description = "计划回款方式", example = "1") |
| 41 | + private Integer returnType; | ||
| 40 | 42 | ||
| 41 | @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") | 43 | @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") |
| 42 | private BigDecimal price; | 44 | private BigDecimal price; |
| 43 | 45 | ||
| 44 | @Schema(description = "回款编号", example = "19852") | 46 | @Schema(description = "回款编号", example = "19852") |
| 45 | private Long receivableId; | 47 | private Long receivableId; |
| 46 | - | ||
| 47 | - @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 48 | - private Boolean finishStatus; | 48 | + @Schema(description = "回款信息") |
| 49 | + private CrmReceivableRespVO receivable; | ||
| 49 | 50 | ||
| 50 | @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 51 | @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 51 | private Integer remindDays; | 52 | private Integer remindDays; |
| @@ -57,12 +58,18 @@ public class CrmReceivablePlanRespVO { | @@ -57,12 +58,18 @@ public class CrmReceivablePlanRespVO { | ||
| 57 | private String remark; | 58 | private String remark; |
| 58 | 59 | ||
| 59 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 60 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 61 | + @ExcelProperty("创建时间") | ||
| 60 | private LocalDateTime createTime; | 62 | private LocalDateTime createTime; |
| 61 | 63 | ||
| 62 | - @Schema(description = "创建人", example = "25682") | ||
| 63 | - private String creator; | 64 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 65 | + @ExcelProperty("更新时间") | ||
| 66 | + private LocalDateTime updateTime; | ||
| 64 | 67 | ||
| 65 | - @Schema(description = "创建人名字", example = "test") | 68 | + @Schema(description = "创建人", example = "1024") |
| 69 | + @ExcelProperty("创建人") | ||
| 70 | + private String creator; | ||
| 71 | + @Schema(description = "创建人名字", example = "芋道源码") | ||
| 72 | + @ExcelProperty("创建人名字") | ||
| 66 | private String creatorName; | 73 | private String creatorName; |
| 67 | 74 | ||
| 68 | } | 75 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java
| @@ -14,9 +14,8 @@ public class CrmReceivablePlanSaveReqVO { | @@ -14,9 +14,8 @@ public class CrmReceivablePlanSaveReqVO { | ||
| 14 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 14 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 15 | private Long id; | 15 | private Long id; |
| 16 | 16 | ||
| 17 | - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 18 | - @NotNull(message = "客户编号不能为空") | ||
| 19 | - private Long customerId; | 17 | + @Schema(description = "客户编号", hidden = true, example = "2") |
| 18 | + private Long customerId; // 该字段不通过前端传递,而是 contractId 查询出来设置进去 | ||
| 20 | 19 | ||
| 21 | @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 20 | @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 22 | @NotNull(message = "合同编号不能为空") | 21 | @NotNull(message = "合同编号不能为空") |
| @@ -37,10 +36,6 @@ public class CrmReceivablePlanSaveReqVO { | @@ -37,10 +36,6 @@ public class CrmReceivablePlanSaveReqVO { | ||
| 37 | @NotNull(message = "计划回款金额不能为空") | 36 | @NotNull(message = "计划回款金额不能为空") |
| 38 | private BigDecimal price; | 37 | private BigDecimal price; |
| 39 | 38 | ||
| 40 | - @Schema(description = "提醒日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 41 | - @NotNull(message = "提醒日期不能为空") | ||
| 42 | - private LocalDateTime remindTime; | ||
| 43 | - | ||
| 44 | @Schema(description = "提前几天提醒", example = "1") | 39 | @Schema(description = "提前几天提醒", example = "1") |
| 45 | private Integer remindDays; | 40 | private Integer remindDays; |
| 46 | 41 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java
| 1 | package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; | 1 | package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; | ||
| 4 | +import com.alibaba.excel.annotation.ExcelProperty; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 6 | import lombok.Data; |
| 5 | 7 | ||
| @@ -31,12 +33,30 @@ public class CrmReceivableRespVO { | @@ -31,12 +33,30 @@ public class CrmReceivableRespVO { | ||
| 31 | 33 | ||
| 32 | @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 34 | @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 33 | private Long customerId; | 35 | private Long customerId; |
| 36 | + @Schema(description = "客户名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") | ||
| 37 | + private String customerName; | ||
| 34 | 38 | ||
| 35 | @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 39 | @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 36 | private Long contractId; | 40 | private Long contractId; |
| 41 | + @Schema(description = "合同信息") | ||
| 42 | + private CrmContractRespVO contract; | ||
| 37 | 43 | ||
| 38 | - @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | 44 | + @Schema(description = "负责人的用户编号", example = "25682") |
| 45 | + @ExcelProperty("负责人的用户编号") | ||
| 39 | private Long ownerUserId; | 46 | private Long ownerUserId; |
| 47 | + @Schema(description = "负责人名字", example = "25682") | ||
| 48 | + @ExcelProperty("负责人名字") | ||
| 49 | + private String ownerUserName; | ||
| 50 | + @Schema(description = "负责人部门") | ||
| 51 | + @ExcelProperty("负责人部门") | ||
| 52 | + private String ownerUserDeptName; | ||
| 53 | + | ||
| 54 | + @Schema(description = "工作流编号", example = "1043") | ||
| 55 | + @ExcelProperty("工作流编号") | ||
| 56 | + private String processInstanceId; | ||
| 57 | + | ||
| 58 | + @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 59 | + private Integer auditStatus; | ||
| 40 | 60 | ||
| 41 | @Schema(description = "备注", example = "备注") | 61 | @Schema(description = "备注", example = "备注") |
| 42 | private String remark; | 62 | private String remark; |
| @@ -44,21 +64,11 @@ public class CrmReceivableRespVO { | @@ -44,21 +64,11 @@ public class CrmReceivableRespVO { | ||
| 44 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 64 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 45 | private LocalDateTime createTime; | 65 | private LocalDateTime createTime; |
| 46 | 66 | ||
| 47 | - @Schema(description = "客户名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") | ||
| 48 | - private String customerName; | ||
| 49 | - | ||
| 50 | - @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 51 | - private Integer auditStatus; | ||
| 52 | - | ||
| 53 | - @Schema(description = "合同编号", example = "Q110") | ||
| 54 | - private String contractNo; | ||
| 55 | - | ||
| 56 | - @Schema(description = "负责人", example = "test") | ||
| 57 | - private String ownerUserName; | 67 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 68 | + private LocalDateTime updateTime; | ||
| 58 | 69 | ||
| 59 | @Schema(description = "创建人", example = "25682") | 70 | @Schema(description = "创建人", example = "25682") |
| 60 | private String creator; | 71 | private String creator; |
| 61 | - | ||
| 62 | @Schema(description = "创建人名字", example = "test") | 72 | @Schema(description = "创建人名字", example = "test") |
| 63 | private String creatorName; | 73 | private String creatorName; |
| 64 | 74 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java
| @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; | @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; | 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum; | 4 | import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum; |
| 5 | +import cn.iocoder.yudao.module.crm.framework.operatelog.core.*; | ||
| 6 | +import com.mzt.logapi.starter.annotation.DiffLogField; | ||
| 5 | import io.swagger.v3.oas.annotations.media.Schema; | 7 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | import jakarta.validation.constraints.NotNull; | 8 | import jakarta.validation.constraints.NotNull; |
| 7 | import lombok.Data; | 9 | import lombok.Data; |
| @@ -16,37 +18,41 @@ public class CrmReceivableSaveReqVO { | @@ -16,37 +18,41 @@ public class CrmReceivableSaveReqVO { | ||
| 16 | @Schema(description = "编号", example = "25787") | 18 | @Schema(description = "编号", example = "25787") |
| 17 | private Long id; | 19 | private Long id; |
| 18 | 20 | ||
| 19 | - @Schema(description = "回款编号", example = "31177") | ||
| 20 | - private String no; | 21 | + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 22 | + @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) | ||
| 23 | + @NotNull(message = "负责人编号不能为空") | ||
| 24 | + private Long ownerUserId; | ||
| 21 | 25 | ||
| 22 | - @Schema(description = "回款计划编号", example = "1024") | ||
| 23 | - private Long planId; // 不是通过回款计划创建的回款没有回款计划编号 | 26 | + @Schema(description = "客户编号", example = "2") |
| 27 | + @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME) | ||
| 28 | + private Long customerId; // 该字段不通过前端传递,而是 contractId 查询出来设置进去 | ||
| 29 | + | ||
| 30 | + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 31 | + @DiffLogField(name = "合同", function = CrmContractParseFunction.NAME) | ||
| 32 | + @NotNull(message = "合同编号不能为空") | ||
| 33 | + private Long contractId; | ||
| 34 | + | ||
| 35 | + @Schema(description = "回款计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 36 | + @DiffLogField(name = "合同", function = CrmReceivablePlanParseFunction.NAME) | ||
| 37 | + private Long planId; | ||
| 24 | 38 | ||
| 25 | @Schema(description = "回款方式", example = "2") | 39 | @Schema(description = "回款方式", example = "2") |
| 40 | + @DiffLogField(name = "回款方式", function = CrmReceivableReturnTypeParseFunction.NAME) | ||
| 26 | @InEnum(CrmReceivableReturnTypeEnum.class) | 41 | @InEnum(CrmReceivableReturnTypeEnum.class) |
| 27 | private Integer returnType; | 42 | private Integer returnType; |
| 28 | 43 | ||
| 29 | @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") | 44 | @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") |
| 45 | + @DiffLogField(name = "回款金额") | ||
| 30 | @NotNull(message = "回款金额不能为空") | 46 | @NotNull(message = "回款金额不能为空") |
| 31 | private BigDecimal price; | 47 | private BigDecimal price; |
| 32 | 48 | ||
| 33 | - @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") | ||
| 34 | - @NotNull(message = "计划回款日期不能为空") | 49 | + @Schema(description = "回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") |
| 50 | + @NotNull(message = "回款日期不能为空") | ||
| 51 | + @DiffLogField(name = "回款日期") | ||
| 35 | private LocalDateTime returnTime; | 52 | private LocalDateTime returnTime; |
| 36 | 53 | ||
| 37 | - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 38 | - @NotNull(message = "客户编号不能为空") | ||
| 39 | - private Long customerId; | ||
| 40 | - | ||
| 41 | - @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 42 | - @NotNull(message = "合同编号不能为空") | ||
| 43 | - private Long contractId; | ||
| 44 | - | ||
| 45 | - @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 46 | - @NotNull(message = "负责人编号不能为空") | ||
| 47 | - private Long ownerUserId; | ||
| 48 | - | ||
| 49 | @Schema(description = "备注", example = "备注") | 54 | @Schema(description = "备注", example = "备注") |
| 55 | + @DiffLogField(name = "备注") | ||
| 50 | private String remark; | 56 | private String remark; |
| 51 | 57 | ||
| 52 | } | 58 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.convert.receivable; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; | ||
| 6 | -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | ||
| 7 | -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.system.api.user.dto.AdminUserRespDTO; | ||
| 10 | -import org.mapstruct.Mapper; | ||
| 11 | -import org.mapstruct.factory.Mappers; | ||
| 12 | - | ||
| 13 | -import java.util.List; | ||
| 14 | -import java.util.Map; | ||
| 15 | - | ||
| 16 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 17 | -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 18 | - | ||
| 19 | -/** | ||
| 20 | - * 回款 Convert | ||
| 21 | - * | ||
| 22 | - * @author 赤焰 | ||
| 23 | - */ | ||
| 24 | -@Mapper | ||
| 25 | -public interface CrmReceivableConvert { | ||
| 26 | - | ||
| 27 | - CrmReceivableConvert INSTANCE = Mappers.getMapper(CrmReceivableConvert.class); | ||
| 28 | - | ||
| 29 | - default PageResult<CrmReceivableRespVO> convertPage(PageResult<CrmReceivableDO> pageResult, Map<Long, AdminUserRespDTO> userMap, | ||
| 30 | - List<CrmCustomerDO> customerList, List<CrmContractDO> contractList) { | ||
| 31 | - PageResult<CrmReceivableRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmReceivableRespVO.class); | ||
| 32 | - // 拼接关联字段 | ||
| 33 | - Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId); | ||
| 34 | - Map<Long, CrmContractDO> contractMap = convertMap(contractList, CrmContractDO::getId); | ||
| 35 | - voPageResult.getList().forEach(receivable -> { | ||
| 36 | - findAndThen(userMap, receivable.getOwnerUserId(), user -> receivable.setOwnerUserName(user.getNickname())); | ||
| 37 | - findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); | ||
| 38 | - findAndThen(customerMap, receivable.getCustomerId(), customer -> receivable.setCustomerName(customer.getName())); | ||
| 39 | - findAndThen(contractMap, receivable.getContractId(), contract -> receivable.setContractNo(contract.getNo())); | ||
| 40 | - }); | ||
| 41 | - return voPageResult; | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.convert.receivable; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; | ||
| 6 | -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | ||
| 7 | -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.CrmReceivablePlanDO; | ||
| 10 | -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 11 | -import org.mapstruct.Mapper; | ||
| 12 | -import org.mapstruct.factory.Mappers; | ||
| 13 | - | ||
| 14 | -import java.util.List; | ||
| 15 | -import java.util.Map; | ||
| 16 | - | ||
| 17 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 18 | -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 19 | - | ||
| 20 | -/** | ||
| 21 | - * 回款计划 Convert | ||
| 22 | - * | ||
| 23 | - * @author 芋道源码 | ||
| 24 | - */ | ||
| 25 | -@Mapper | ||
| 26 | -public interface CrmReceivablePlanConvert { | ||
| 27 | - | ||
| 28 | - CrmReceivablePlanConvert INSTANCE = Mappers.getMapper(CrmReceivablePlanConvert.class); | ||
| 29 | - | ||
| 30 | - default PageResult<CrmReceivablePlanRespVO> convertPage(PageResult<CrmReceivablePlanDO> pageResult, Map<Long, AdminUserRespDTO> userMap, | ||
| 31 | - List<CrmCustomerDO> customerList, List<CrmContractDO> contractList, | ||
| 32 | - List<CrmReceivableDO> receivableList) { | ||
| 33 | - PageResult<CrmReceivablePlanRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmReceivablePlanRespVO.class); | ||
| 34 | - // 拼接关联字段 | ||
| 35 | - Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId); | ||
| 36 | - Map<Long, CrmContractDO> contractMap = convertMap(contractList, CrmContractDO::getId); | ||
| 37 | - Map<Long, CrmReceivableDO> receivableMap = convertMap(receivableList, CrmReceivableDO::getId); | ||
| 38 | - voPageResult.getList().forEach(receivablePlan -> { | ||
| 39 | - findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname())); | ||
| 40 | - findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); | ||
| 41 | - findAndThen(customerMap, receivablePlan.getCustomerId(), customer -> receivablePlan.setCustomerName(customer.getName())); | ||
| 42 | - findAndThen(contractMap, receivablePlan.getContractId(), contract -> receivablePlan.setContractNo(contract.getNo())); | ||
| 43 | - findAndThen(receivableMap, receivablePlan.getReceivableId(), receivable -> receivablePlan.setReturnType(receivable.getReturnType())); | ||
| 44 | - }); | ||
| 45 | - return voPageResult; | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java
| @@ -39,15 +39,21 @@ public class CrmReceivableDO extends BaseDO { | @@ -39,15 +39,21 @@ public class CrmReceivableDO extends BaseDO { | ||
| 39 | */ | 39 | */ |
| 40 | private String no; | 40 | private String no; |
| 41 | /** | 41 | /** |
| 42 | - * 回款计划编号,关联 {@link CrmReceivablePlanDO#getId()} | 42 | + * 回款计划编号 |
| 43 | + * | ||
| 44 | + * 关联 {@link CrmReceivablePlanDO#getId()},非必须 | ||
| 43 | */ | 45 | */ |
| 44 | private Long planId; | 46 | private Long planId; |
| 45 | /** | 47 | /** |
| 46 | - * 客户编号,关联 {@link CrmCustomerDO#getId()} | 48 | + * 客户编号 |
| 49 | + * | ||
| 50 | + * 关联 {@link CrmCustomerDO#getId()} | ||
| 47 | */ | 51 | */ |
| 48 | private Long customerId; | 52 | private Long customerId; |
| 49 | /** | 53 | /** |
| 50 | - * 合同编号,关联 {@link CrmContractDO#getId()} | 54 | + * 合同编号 |
| 55 | + * | ||
| 56 | + * 关联 {@link CrmContractDO#getId()} | ||
| 51 | */ | 57 | */ |
| 52 | private Long contractId; | 58 | private Long contractId; |
| 53 | /** | 59 | /** |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java
| @@ -61,7 +61,7 @@ public class CrmReceivablePlanDO extends BaseDO { | @@ -61,7 +61,7 @@ public class CrmReceivablePlanDO extends BaseDO { | ||
| 61 | */ | 61 | */ |
| 62 | private LocalDateTime returnTime; | 62 | private LocalDateTime returnTime; |
| 63 | /** | 63 | /** |
| 64 | - * 回款类型 | 64 | + * 计划回款类型 |
| 65 | * | 65 | * |
| 66 | * 枚举 {@link CrmReceivableReturnTypeEnum} | 66 | * 枚举 {@link CrmReceivableReturnTypeEnum} |
| 67 | */ | 67 | */ |
| @@ -75,10 +75,6 @@ public class CrmReceivablePlanDO extends BaseDO { | @@ -75,10 +75,6 @@ public class CrmReceivablePlanDO extends BaseDO { | ||
| 75 | * 回款编号,关联 {@link CrmReceivableDO#getId()} | 75 | * 回款编号,关联 {@link CrmReceivableDO#getId()} |
| 76 | */ | 76 | */ |
| 77 | private Long receivableId; | 77 | private Long receivableId; |
| 78 | - /** | ||
| 79 | - * 完成状态 | ||
| 80 | - */ | ||
| 81 | - private Boolean finishStatus; | ||
| 82 | 78 | ||
| 83 | /** | 79 | /** |
| 84 | * 提前几天提醒 | 80 | * 提前几天提醒 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/package-info.java deleted
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
| 1 | package cn.iocoder.yudao.module.crm.dal.mysql.receivable; | 1 | package cn.iocoder.yudao.module.crm.dal.mysql.receivable; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | 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.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| @@ -11,10 +12,16 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; | @@ -11,10 +12,16 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; | ||
| 11 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 12 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 12 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; |
| 13 | import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; | 14 | import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; |
| 15 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 14 | import org.apache.ibatis.annotations.Mapper; | 16 | import org.apache.ibatis.annotations.Mapper; |
| 15 | 17 | ||
| 18 | +import java.math.BigDecimal; | ||
| 16 | import java.util.Collection; | 19 | import java.util.Collection; |
| 20 | +import java.util.Collections; | ||
| 17 | import java.util.List; | 21 | import java.util.List; |
| 22 | +import java.util.Map; | ||
| 23 | + | ||
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 18 | 25 | ||
| 19 | /** | 26 | /** |
| 20 | * 回款 Mapper | 27 | * 回款 Mapper |
| @@ -24,6 +31,10 @@ import java.util.List; | @@ -24,6 +31,10 @@ import java.util.List; | ||
| 24 | @Mapper | 31 | @Mapper |
| 25 | public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | 32 | public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { |
| 26 | 33 | ||
| 34 | + default CrmReceivableDO selectByNo(String no) { | ||
| 35 | + return selectOne(CrmReceivableDO::getNo, no); | ||
| 36 | + } | ||
| 37 | + | ||
| 27 | default PageResult<CrmReceivableDO> selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { | 38 | default PageResult<CrmReceivableDO> selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { |
| 28 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() | 39 | return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() |
| 29 | .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 | 40 | .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 |
| @@ -67,4 +78,18 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | @@ -67,4 +78,18 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | ||
| 67 | return selectCount(query); | 78 | return selectCount(query); |
| 68 | } | 79 | } |
| 69 | 80 | ||
| 81 | + default Map<Long, BigDecimal> selectReceivablePriceMapByContractId(Collection<Long> contractIds) { | ||
| 82 | + if (CollUtil.isEmpty(contractIds)) { | ||
| 83 | + return Collections.emptyMap(); | ||
| 84 | + } | ||
| 85 | + // SQL sum 查询 | ||
| 86 | + List<Map<String, Object>> result = selectMaps(new QueryWrapper<CrmReceivableDO>() | ||
| 87 | + .select("contract_id, SUM(price) AS total_price") | ||
| 88 | + .eq("audit_status", CrmAuditStatusEnum.APPROVE.getStatus()) | ||
| 89 | + .groupBy("contract_id") | ||
| 90 | + .in("contract_id", contractIds)); | ||
| 91 | + // 获得金额 | ||
| 92 | + return convertMap(result, obj -> (Long) obj.get("contract_id"), obj -> (BigDecimal) obj.get("total_price")); | ||
| 93 | + } | ||
| 94 | + | ||
| 70 | } | 95 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
| @@ -25,6 +25,13 @@ import java.util.Objects; | @@ -25,6 +25,13 @@ import java.util.Objects; | ||
| 25 | @Mapper | 25 | @Mapper |
| 26 | public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> { | 26 | public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> { |
| 27 | 27 | ||
| 28 | + default CrmReceivablePlanDO selectMaxPeriodByContractId(Long contractId) { | ||
| 29 | + return selectOne(new MPJLambdaWrapperX<CrmReceivablePlanDO>() | ||
| 30 | + .eq(CrmReceivablePlanDO::getContractId, contractId) | ||
| 31 | + .orderByDesc(CrmReceivablePlanDO::getPeriod) | ||
| 32 | + .last("LIMIT 1")); | ||
| 33 | + } | ||
| 34 | + | ||
| 28 | default PageResult<CrmReceivablePlanDO> selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) { | 35 | default PageResult<CrmReceivablePlanDO> selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) { |
| 29 | MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); | 36 | MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); |
| 30 | if (Objects.nonNull(reqVO.getContractNo())) { // 根据合同编号检索 | 37 | if (Objects.nonNull(reqVO.getContractNo())) { // 根据合同编号检索 |
| @@ -47,7 +54,6 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | @@ -47,7 +54,6 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||
| 47 | .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) | 54 | .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) |
| 48 | .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) | 55 | .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) |
| 49 | .orderByDesc(CrmReceivablePlanDO::getPeriod); | 56 | .orderByDesc(CrmReceivablePlanDO::getPeriod); |
| 50 | - | ||
| 51 | if (Objects.nonNull(pageReqVO.getContractNo())) { // 根据合同编号检索 | 57 | if (Objects.nonNull(pageReqVO.getContractNo())) { // 根据合同编号检索 |
| 52 | query.innerJoin(CrmContractDO.class, on -> on.like(CrmContractDO::getNo, pageReqVO.getContractNo()) | 58 | query.innerJoin(CrmContractDO.class, on -> on.like(CrmContractDO::getNo, pageReqVO.getContractNo()) |
| 53 | .eq(CrmContractDO::getId, CrmReceivablePlanDO::getContractId)); | 59 | .eq(CrmContractDO::getId, CrmReceivablePlanDO::getContractId)); |
| @@ -67,9 +73,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | @@ -67,9 +73,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||
| 67 | } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款 | 73 | } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款 |
| 68 | query.isNotNull(CrmReceivablePlanDO::getReceivableId) | 74 | query.isNotNull(CrmReceivablePlanDO::getReceivableId) |
| 69 | .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); | 75 | .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); |
| 70 | - ; | ||
| 71 | } | 76 | } |
| 72 | - | ||
| 73 | return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); | 77 | return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); |
| 74 | } | 78 | } |
| 75 | 79 | ||
| @@ -93,6 +97,9 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | @@ -93,6 +97,9 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||
| 93 | LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); | 97 | LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); |
| 94 | query.isNull(CrmReceivablePlanDO::getReceivableId) | 98 | query.isNull(CrmReceivablePlanDO::getReceivableId) |
| 95 | .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); | 99 | .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); |
| 100 | + // TODO return_time 小于现在; | ||
| 101 | + // TODO 未回款 | ||
| 102 | + // TODO remind_time 大于现在; | ||
| 96 | return selectCount(query); | 103 | return selectCount(query); |
| 97 | } | 104 | } |
| 98 | 105 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
| @@ -25,7 +25,7 @@ public class CrmNoRedisDAO { | @@ -25,7 +25,7 @@ public class CrmNoRedisDAO { | ||
| 25 | public static final String CONTRACT_NO_PREFIX = "HT"; | 25 | public static final String CONTRACT_NO_PREFIX = "HT"; |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | - * 还款 {@link cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO} | 28 | + * 回款 {@link cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO} |
| 29 | */ | 29 | */ |
| 30 | public static final String RECEIVABLE_PREFIX = "HK"; | 30 | public static final String RECEIVABLE_PREFIX = "HK"; |
| 31 | 31 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.operatelog.core; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | ||
| 5 | +import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivablePlanService; | ||
| 6 | +import com.mzt.logapi.service.IParseFunction; | ||
| 7 | +import jakarta.annotation.Resource; | ||
| 8 | +import lombok.extern.slf4j.Slf4j; | ||
| 9 | +import org.springframework.stereotype.Component; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * CRM 回款计划的 {@link IParseFunction} 实现类 | ||
| 13 | + * | ||
| 14 | + * @author HUIHUI | ||
| 15 | + */ | ||
| 16 | +@Component | ||
| 17 | +@Slf4j | ||
| 18 | +public class CrmReceivablePlanParseFunction implements IParseFunction { | ||
| 19 | + | ||
| 20 | + public static final String NAME = "getReceivablePlanServiceById"; | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private CrmReceivablePlanService receivablePlanService; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public boolean executeBefore() { | ||
| 27 | + return true; // 先转换值后对比 | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public String functionName() { | ||
| 32 | + return NAME; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public String apply(Object value) { | ||
| 37 | + if (StrUtil.isEmptyIfStr(value)) { | ||
| 38 | + return ""; | ||
| 39 | + } | ||
| 40 | + CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(Long.parseLong(value.toString())); | ||
| 41 | + return receivablePlan == null ? "" : receivablePlan.getPeriod().toString(); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | +} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.operatelog.core; | ||
| 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_RECEIVABLE_RETURN_TYPE; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * CRM 回款方式的 {@link IParseFunction} 实现类 | ||
| 13 | + * | ||
| 14 | + * @author HUIHUI | ||
| 15 | + */ | ||
| 16 | +@Slf4j | ||
| 17 | +@Component | ||
| 18 | +public class CrmReceivableReturnTypeParseFunction implements IParseFunction { | ||
| 19 | + | ||
| 20 | + public static final String NAME = "getReceivableReturnType"; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public boolean executeBefore() { | ||
| 24 | + return true; // 先转换值后对比 | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public String functionName() { | ||
| 29 | + return NAME; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public String apply(Object value) { | ||
| 34 | + if (StrUtil.isEmptyIfStr(value)) { | ||
| 35 | + return ""; | ||
| 36 | + } | ||
| 37 | + return DictFrameworkUtils.getDictDataLabel(CRM_RECEIVABLE_RETURN_TYPE, value.toString()); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | +} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
| @@ -13,6 +13,9 @@ import jakarta.validation.Valid; | @@ -13,6 +13,9 @@ import jakarta.validation.Valid; | ||
| 13 | import java.time.LocalDateTime; | 13 | import java.time.LocalDateTime; |
| 14 | import java.util.Collection; | 14 | import java.util.Collection; |
| 15 | import java.util.List; | 15 | import java.util.List; |
| 16 | +import java.util.Map; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 16 | 19 | ||
| 17 | /** | 20 | /** |
| 18 | * CRM 合同 Service 接口 | 21 | * CRM 合同 Service 接口 |
| @@ -86,6 +89,14 @@ public interface CrmContractService { | @@ -86,6 +89,14 @@ public interface CrmContractService { | ||
| 86 | CrmContractDO getContract(Long id); | 89 | CrmContractDO getContract(Long id); |
| 87 | 90 | ||
| 88 | /** | 91 | /** |
| 92 | + * 校验合同是否合法 | ||
| 93 | + * | ||
| 94 | + * @param id 编号 | ||
| 95 | + * @return 合同 | ||
| 96 | + */ | ||
| 97 | + CrmContractDO validateContract(Long id); | ||
| 98 | + | ||
| 99 | + /** | ||
| 89 | * 获得合同列表 | 100 | * 获得合同列表 |
| 90 | * | 101 | * |
| 91 | * @param ids 编号 | 102 | * @param ids 编号 |
| @@ -94,6 +105,16 @@ public interface CrmContractService { | @@ -94,6 +105,16 @@ public interface CrmContractService { | ||
| 94 | List<CrmContractDO> getContractList(Collection<Long> ids); | 105 | List<CrmContractDO> getContractList(Collection<Long> ids); |
| 95 | 106 | ||
| 96 | /** | 107 | /** |
| 108 | + * 获得合同 Map | ||
| 109 | + * | ||
| 110 | + * @param ids 编号 | ||
| 111 | + * @return 合同 Map | ||
| 112 | + */ | ||
| 113 | + default Map<Long, CrmContractDO> getContractMap(Collection<Long> ids) { | ||
| 114 | + return convertMap(getContractList(ids), CrmContractDO::getId); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + /** | ||
| 97 | * 获得合同分页 | 118 | * 获得合同分页 |
| 98 | * | 119 | * |
| 99 | * 数据权限:基于 {@link CrmContractDO} 读取 | 120 | * 数据权限:基于 {@link CrmContractDO} 读取 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
| @@ -324,6 +324,11 @@ public class CrmContractServiceImpl implements CrmContractService { | @@ -324,6 +324,11 @@ public class CrmContractServiceImpl implements CrmContractService { | ||
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | @Override | 326 | @Override |
| 327 | + public CrmContractDO validateContract(Long id) { | ||
| 328 | + return validateContractExists(id); | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + @Override | ||
| 327 | public List<CrmContractDO> getContractList(Collection<Long> ids) { | 332 | public List<CrmContractDO> getContractList(Collection<Long> ids) { |
| 328 | if (CollUtil.isEmpty(ids)) { | 333 | if (CollUtil.isEmpty(ids)) { |
| 329 | return ListUtil.empty(); | 334 | return ListUtil.empty(); |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
| @@ -38,7 +38,7 @@ public interface CrmReceivablePlanService { | @@ -38,7 +38,7 @@ public interface CrmReceivablePlanService { | ||
| 38 | * @param id 编号 | 38 | * @param id 编号 |
| 39 | * @param receivableId 回款编号 | 39 | * @param receivableId 回款编号 |
| 40 | */ | 40 | */ |
| 41 | - void updateReceivableId(Long id, Long receivableId); | 41 | + void updateReceivablePlanReceivableId(Long id, Long receivableId); |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * 删除回款计划 | 44 | * 删除回款计划 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
| @@ -2,20 +2,17 @@ package cn.iocoder.yudao.module.crm.service.receivable; | @@ -2,20 +2,17 @@ package cn.iocoder.yudao.module.crm.service.receivable; | ||
| 2 | 2 | ||
| 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.hutool.core.util.ObjectUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 8 | 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; |
| 9 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; | 8 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 11 | -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 13 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; | 11 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; |
| 14 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 12 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 15 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 16 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | 14 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 17 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 15 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 18 | -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||
| 19 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 20 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 21 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 18 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -33,7 +30,8 @@ import java.util.List; | @@ -33,7 +30,8 @@ import java.util.List; | ||
| 33 | import java.util.Objects; | 30 | import java.util.Objects; |
| 34 | 31 | ||
| 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 32 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 36 | -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | 33 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PLAN_NOT_EXISTS; |
| 34 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PLAN_UPDATE_FAIL; | ||
| 37 | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | 35 | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; |
| 38 | 36 | ||
| 39 | /** | 37 | /** |
| @@ -54,8 +52,6 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -54,8 +52,6 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 54 | @Resource | 52 | @Resource |
| 55 | private CrmContractService contractService; | 53 | private CrmContractService contractService; |
| 56 | @Resource | 54 | @Resource |
| 57 | - private CrmCustomerService customerService; | ||
| 58 | - @Resource | ||
| 59 | private CrmPermissionService permissionService; | 55 | private CrmPermissionService permissionService; |
| 60 | 56 | ||
| 61 | @Resource | 57 | @Resource |
| @@ -66,15 +62,16 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -66,15 +62,16 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 66 | @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_CREATE_SUB_TYPE, bizNo = "{{#receivablePlan.id}}", | 62 | @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_CREATE_SUB_TYPE, bizNo = "{{#receivablePlan.id}}", |
| 67 | success = CRM_RECEIVABLE_PLAN_CREATE_SUCCESS) | 63 | success = CRM_RECEIVABLE_PLAN_CREATE_SUCCESS) |
| 68 | public Long createReceivablePlan(CrmReceivablePlanSaveReqVO createReqVO) { | 64 | public Long createReceivablePlan(CrmReceivablePlanSaveReqVO createReqVO) { |
| 69 | - // 1.1 校验关联数据是否存在 | 65 | + // 1. 校验关联数据是否存在 |
| 70 | validateRelationDataExists(createReqVO); | 66 | validateRelationDataExists(createReqVO); |
| 71 | - // 1.2 查验关联合同回款数量 | ||
| 72 | - Long count = receivableService.getReceivableCountByContractId(createReqVO.getContractId()); | ||
| 73 | - int period = (int) (count + 1); | ||
| 74 | 67 | ||
| 75 | - // 2. 插入还款计划 | ||
| 76 | - CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class) | ||
| 77 | - .setPeriod(period).setFinishStatus(false); | 68 | + // 2. 插入回款计划 |
| 69 | + CrmReceivablePlanDO maxPeriodReceivablePlan = receivablePlanMapper.selectMaxPeriodByContractId(createReqVO.getContractId()); | ||
| 70 | + int period = maxPeriodReceivablePlan == null ? 1 : maxPeriodReceivablePlan.getPeriod() + 1; | ||
| 71 | + CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setPeriod(period); | ||
| 72 | + if (createReqVO.getReturnTime() != null && createReqVO.getRemindDays() != null) { | ||
| 73 | + receivablePlan.setRemindTime(createReqVO.getReturnTime().minusDays(createReqVO.getRemindDays())); | ||
| 74 | + } | ||
| 78 | receivablePlanMapper.insert(receivablePlan); | 75 | receivablePlanMapper.insert(receivablePlan); |
| 79 | 76 | ||
| 80 | // 3. 创建数据权限 | 77 | // 3. 创建数据权限 |
| @@ -93,15 +90,21 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -93,15 +90,21 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 93 | success = CRM_RECEIVABLE_PLAN_UPDATE_SUCCESS) | 90 | success = CRM_RECEIVABLE_PLAN_UPDATE_SUCCESS) |
| 94 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | 91 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 95 | public void updateReceivablePlan(CrmReceivablePlanSaveReqVO updateReqVO) { | 92 | public void updateReceivablePlan(CrmReceivablePlanSaveReqVO updateReqVO) { |
| 96 | - // 1. 校验存在 | 93 | + updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null); // 防止修改这些字段 |
| 94 | + // 1.1 校验存在 | ||
| 97 | validateRelationDataExists(updateReqVO); | 95 | validateRelationDataExists(updateReqVO); |
| 96 | + // 1.2 校验关联数据是否存在 | ||
| 98 | CrmReceivablePlanDO oldReceivablePlan = validateReceivablePlanExists(updateReqVO.getId()); | 97 | CrmReceivablePlanDO oldReceivablePlan = validateReceivablePlanExists(updateReqVO.getId()); |
| 99 | - if (Objects.nonNull(oldReceivablePlan.getReceivableId())) { // 如果已经有对应的还款,则不允许编辑; | ||
| 100 | - throw exception(RECEIVABLE_PLAN_UPDATE_FAIL, "已经有对应的还款"); | 98 | + // 1.3 如果已经有对应的回款,则不允许编辑 |
| 99 | + if (Objects.nonNull(oldReceivablePlan.getReceivableId())) { | ||
| 100 | + throw exception(RECEIVABLE_PLAN_UPDATE_FAIL); | ||
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | - // 2. 更新 | 103 | + // 2. 更新回款计划 |
| 104 | CrmReceivablePlanDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivablePlanDO.class); | 104 | CrmReceivablePlanDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivablePlanDO.class); |
| 105 | + if (updateReqVO.getReturnTime() != null && updateReqVO.getRemindDays() != null) { | ||
| 106 | + updateObj.setRemindTime(updateReqVO.getReturnTime().minusDays(updateReqVO.getRemindDays())); | ||
| 107 | + } | ||
| 105 | receivablePlanMapper.updateById(updateObj); | 108 | receivablePlanMapper.updateById(updateObj); |
| 106 | 109 | ||
| 107 | // 3. 记录操作日志上下文 | 110 | // 3. 记录操作日志上下文 |
| @@ -109,24 +112,24 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -109,24 +112,24 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 109 | LogRecordContext.putVariable("receivablePlan", oldReceivablePlan); | 112 | LogRecordContext.putVariable("receivablePlan", oldReceivablePlan); |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 115 | + private void validateRelationDataExists(CrmReceivablePlanSaveReqVO reqVO) { | ||
| 116 | + // 校验负责人存在 | ||
| 117 | + if (reqVO.getOwnerUserId() != null) { | ||
| 118 | + adminUserApi.validateUser(reqVO.getOwnerUserId()); | ||
| 119 | + } | ||
| 120 | + // 校验合同存在 | ||
| 121 | + if (reqVO.getContractId() != null) { | ||
| 122 | + CrmContractDO contract = contractService.getContract(reqVO.getContractId()); | ||
| 123 | + reqVO.setCustomerId(contract.getCustomerId()); | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + | ||
| 112 | @Override | 127 | @Override |
| 113 | - public void updateReceivableId(Long id, Long receivableId) { | 128 | + public void updateReceivablePlanReceivableId(Long id, Long receivableId) { |
| 114 | // 校验存在 | 129 | // 校验存在 |
| 115 | validateReceivablePlanExists(id); | 130 | validateReceivablePlanExists(id); |
| 116 | // 更新回款计划 | 131 | // 更新回款计划 |
| 117 | - receivablePlanMapper.updateById(new CrmReceivablePlanDO().setReceivableId(receivableId).setFinishStatus(true)); | ||
| 118 | - } | ||
| 119 | - | ||
| 120 | - private void validateRelationDataExists(CrmReceivablePlanSaveReqVO reqVO) { | ||
| 121 | - adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 | ||
| 122 | - CrmContractDO contract = contractService.getContract(reqVO.getContractId()); | ||
| 123 | - if (ObjectUtil.isNull(contract)) { // 合同不存在 | ||
| 124 | - throw exception(CONTRACT_NOT_EXISTS); | ||
| 125 | - } | ||
| 126 | - CrmCustomerDO customer = customerService.getCustomer(reqVO.getCustomerId()); | ||
| 127 | - if (ObjectUtil.isNull(customer)) { // 客户不存在 | ||
| 128 | - throw exception(CUSTOMER_NOT_EXISTS); | ||
| 129 | - } | 132 | + receivablePlanMapper.updateById(new CrmReceivablePlanDO().setId(id).setReceivableId(receivableId)); |
| 130 | } | 133 | } |
| 131 | 134 | ||
| 132 | @Override | 135 | @Override |
| @@ -135,13 +138,15 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | @@ -135,13 +138,15 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||
| 135 | success = CRM_RECEIVABLE_PLAN_DELETE_SUCCESS) | 138 | success = CRM_RECEIVABLE_PLAN_DELETE_SUCCESS) |
| 136 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | 139 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 137 | public void deleteReceivablePlan(Long id) { | 140 | public void deleteReceivablePlan(Long id) { |
| 138 | - // 校验存在 | 141 | + // 1. 校验存在 |
| 139 | CrmReceivablePlanDO receivablePlan = validateReceivablePlanExists(id); | 142 | CrmReceivablePlanDO receivablePlan = validateReceivablePlanExists(id); |
| 140 | - // 删除 | 143 | + |
| 144 | + // 2. 删除 | ||
| 141 | receivablePlanMapper.deleteById(id); | 145 | receivablePlanMapper.deleteById(id); |
| 142 | - // 删除数据权限 | 146 | + // 3. 删除数据权限 |
| 143 | permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); | 147 | permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); |
| 144 | - // 记录操作日志上下文 | 148 | + |
| 149 | + // 4. 记录操作日志上下文 | ||
| 145 | LogRecordContext.putVariable("receivablePlan", receivablePlan); | 150 | LogRecordContext.putVariable("receivablePlan", receivablePlan); |
| 146 | } | 151 | } |
| 147 | 152 |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
| @@ -7,8 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | @@ -7,8 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 8 | import jakarta.validation.Valid; | 8 | import jakarta.validation.Valid; |
| 9 | 9 | ||
| 10 | +import java.math.BigDecimal; | ||
| 10 | import java.util.Collection; | 11 | import java.util.Collection; |
| 11 | import java.util.List; | 12 | import java.util.List; |
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 12 | 16 | ||
| 13 | /** | 17 | /** |
| 14 | * CRM 回款 Service 接口 | 18 | * CRM 回款 Service 接口 |
| @@ -72,6 +76,16 @@ public interface CrmReceivableService { | @@ -72,6 +76,16 @@ public interface CrmReceivableService { | ||
| 72 | List<CrmReceivableDO> getReceivableList(Collection<Long> ids); | 76 | List<CrmReceivableDO> getReceivableList(Collection<Long> ids); |
| 73 | 77 | ||
| 74 | /** | 78 | /** |
| 79 | + * 获得回款 Map | ||
| 80 | + * | ||
| 81 | + * @param ids 编号 | ||
| 82 | + * @return 回款 Map | ||
| 83 | + */ | ||
| 84 | + default Map<Long, CrmReceivableDO> getReceivableMap(Collection<Long> ids) { | ||
| 85 | + return convertMap(getReceivableList(ids), CrmReceivableDO::getId); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /** | ||
| 75 | * 获得回款分页 | 89 | * 获得回款分页 |
| 76 | * | 90 | * |
| 77 | * 数据权限:基于 {@link CrmReceivableDO} 读取 | 91 | * 数据权限:基于 {@link CrmReceivableDO} 读取 |
| @@ -101,11 +115,11 @@ public interface CrmReceivableService { | @@ -101,11 +115,11 @@ public interface CrmReceivableService { | ||
| 101 | Long getCheckReceivablesCount(Long userId); | 115 | Long getCheckReceivablesCount(Long userId); |
| 102 | 116 | ||
| 103 | /** | 117 | /** |
| 104 | - * 根据合同编号,获取合同关联的回款数量 | 118 | + * 获得合同已回款金额 Map |
| 105 | * | 119 | * |
| 106 | - * @param contractId 合同编号 | ||
| 107 | - * @return 数量 | 120 | + * @param contractIds 合同编号 |
| 121 | + * @return 回款金额 Map | ||
| 108 | */ | 122 | */ |
| 109 | - Long getReceivableCountByContractId(Long contractId); | 123 | + Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds); |
| 110 | 124 | ||
| 111 | } | 125 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
| @@ -13,16 +13,15 @@ import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; | @@ -13,16 +13,15 @@ import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; | ||
| 13 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; | 13 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; |
| 14 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; | 14 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; |
| 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| 18 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; |
| 19 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; | 18 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; |
| 19 | +import cn.iocoder.yudao.module.crm.dal.redis.no.CrmNoRedisDAO; | ||
| 20 | import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; | 20 | import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; |
| 21 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 21 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 22 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 22 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 23 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | 23 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 24 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 24 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 25 | -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||
| 26 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 25 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 27 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 26 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 28 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 27 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -36,9 +35,10 @@ import org.springframework.stereotype.Service; | @@ -36,9 +35,10 @@ import org.springframework.stereotype.Service; | ||
| 36 | import org.springframework.transaction.annotation.Transactional; | 35 | import org.springframework.transaction.annotation.Transactional; |
| 37 | import org.springframework.validation.annotation.Validated; | 36 | import org.springframework.validation.annotation.Validated; |
| 38 | 37 | ||
| 38 | +import java.math.BigDecimal; | ||
| 39 | import java.util.Collection; | 39 | import java.util.Collection; |
| 40 | import java.util.List; | 40 | import java.util.List; |
| 41 | -import java.util.Objects; | 41 | +import java.util.Map; |
| 42 | 42 | ||
| 43 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 43 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 44 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | 44 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| @@ -56,17 +56,18 @@ import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmRes | @@ -56,17 +56,18 @@ import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmRes | ||
| 56 | public class CrmReceivableServiceImpl implements CrmReceivableService { | 56 | public class CrmReceivableServiceImpl implements CrmReceivableService { |
| 57 | 57 | ||
| 58 | /** | 58 | /** |
| 59 | - * BPM 回款审批流程标识 | 59 | + * BPM 合同审批流程标识 |
| 60 | */ | 60 | */ |
| 61 | - public static final String RECEIVABLE_APPROVE = "receivable-approve"; | 61 | + public static final String BPM_PROCESS_DEFINITION_KEY = "crm-receivable-audit"; |
| 62 | 62 | ||
| 63 | @Resource | 63 | @Resource |
| 64 | private CrmReceivableMapper receivableMapper; | 64 | private CrmReceivableMapper receivableMapper; |
| 65 | 65 | ||
| 66 | @Resource | 66 | @Resource |
| 67 | - private CrmContractService contractService; | 67 | + private CrmNoRedisDAO noRedisDAO; |
| 68 | + | ||
| 68 | @Resource | 69 | @Resource |
| 69 | - private CrmCustomerService customerService; | 70 | + private CrmContractService contractService; |
| 70 | @Resource | 71 | @Resource |
| 71 | @Lazy // 延迟加载,避免循环依赖 | 72 | @Lazy // 延迟加载,避免循环依赖 |
| 72 | private CrmReceivablePlanService receivablePlanService; | 73 | private CrmReceivablePlanService receivablePlanService; |
| @@ -78,48 +79,63 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -78,48 +79,63 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 78 | @Resource | 79 | @Resource |
| 79 | private BpmProcessInstanceApi bpmProcessInstanceApi; | 80 | private BpmProcessInstanceApi bpmProcessInstanceApi; |
| 80 | 81 | ||
| 82 | + // TODO @puhui999:操作日志没记录上 | ||
| 81 | @Override | 83 | @Override |
| 82 | @Transactional(rollbackFor = Exception.class) | 84 | @Transactional(rollbackFor = Exception.class) |
| 83 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}", | 85 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}", |
| 84 | success = CRM_RECEIVABLE_CREATE_SUCCESS) | 86 | success = CRM_RECEIVABLE_CREATE_SUCCESS) |
| 85 | public Long createReceivable(CrmReceivableSaveReqVO createReqVO) { | 87 | public Long createReceivable(CrmReceivableSaveReqVO createReqVO) { |
| 86 | - // 1. 校验关联数据存在 | 88 | + // 1.1 校验关联数据存在 |
| 87 | validateRelationDataExists(createReqVO); | 89 | validateRelationDataExists(createReqVO); |
| 88 | - // 2. 插入还款 | ||
| 89 | - CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); | 90 | + // 1.2 生成回款编号 |
| 91 | + String no = noRedisDAO.generate(CrmNoRedisDAO.RECEIVABLE_PREFIX); | ||
| 92 | + if (receivableMapper.selectByNo(no) != null) { | ||
| 93 | + throw exception(RECEIVABLE_NO_EXISTS); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + // 2. 插入回款 | ||
| 97 | + CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class) | ||
| 98 | + .setNo(no).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); | ||
| 90 | receivableMapper.insert(receivable); | 99 | receivableMapper.insert(receivable); |
| 100 | + | ||
| 91 | // 3. 创建数据权限 | 101 | // 3. 创建数据权限 |
| 92 | permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()) | 102 | permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()) |
| 93 | - .setBizId(receivable.getId()).setUserId(createReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | 103 | + .setBizId(receivable.getId()).setUserId(createReqVO.getOwnerUserId()) |
| 104 | + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | ||
| 105 | + | ||
| 94 | // 4. 更新关联的回款计划 | 106 | // 4. 更新关联的回款计划 |
| 95 | - if (Objects.nonNull(createReqVO.getPlanId())) { | ||
| 96 | - receivablePlanService.updateReceivableId(receivable.getPlanId(), receivable.getId()); | 107 | + if (createReqVO.getPlanId() != null) { |
| 108 | + receivablePlanService.updateReceivablePlanReceivableId(receivable.getPlanId(), receivable.getId()); | ||
| 97 | } | 109 | } |
| 110 | + | ||
| 98 | // 5. 记录操作日志上下文 | 111 | // 5. 记录操作日志上下文 |
| 99 | LogRecordContext.putVariable("receivable", receivable); | 112 | LogRecordContext.putVariable("receivable", receivable); |
| 100 | return receivable.getId(); | 113 | return receivable.getId(); |
| 101 | } | 114 | } |
| 102 | 115 | ||
| 103 | private void validateRelationDataExists(CrmReceivableSaveReqVO reqVO) { | 116 | private void validateRelationDataExists(CrmReceivableSaveReqVO reqVO) { |
| 104 | - adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 | ||
| 105 | - CrmContractDO contract = contractService.getContract(reqVO.getContractId()); | ||
| 106 | - if (ObjectUtil.isNull(contract)) { | ||
| 107 | - throw exception(CONTRACT_NOT_EXISTS); | ||
| 108 | - } | ||
| 109 | - CrmCustomerDO customer = customerService.getCustomer(reqVO.getCustomerId()); | ||
| 110 | - if (ObjectUtil.isNull(customer)) { | ||
| 111 | - throw exception(CUSTOMER_NOT_EXISTS); | 117 | + if (reqVO.getOwnerUserId() != null) { |
| 118 | + adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 | ||
| 112 | } | 119 | } |
| 113 | - if (Objects.isNull(reqVO.getPlanId())) { // 没有回款计划编号则不校验 | ||
| 114 | - return; | 120 | + if (reqVO.getContractId() != null) { |
| 121 | + CrmContractDO contract = contractService.validateContract(reqVO.getContractId()); | ||
| 122 | + if (ObjectUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.APPROVE.getStatus())) { | ||
| 123 | + throw exception(RECEIVABLE_CREATE_FAIL_CONTRACT_NOT_APPROVE); | ||
| 124 | + } | ||
| 125 | + reqVO.setCustomerId(contract.getCustomerId()); // 设置客户编号 | ||
| 115 | } | 126 | } |
| 116 | - CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(reqVO.getPlanId()); | ||
| 117 | - if (ObjectUtil.isNull(receivablePlan)) { | ||
| 118 | - throw exception(RECEIVABLE_PLAN_NOT_EXISTS); | 127 | + if (reqVO.getPlanId() != null) { |
| 128 | + CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(reqVO.getPlanId()); | ||
| 129 | + if (receivablePlan == null) { | ||
| 130 | + throw exception(RECEIVABLE_PLAN_NOT_EXISTS); | ||
| 131 | + } | ||
| 132 | + if (receivablePlan.getReceivableId() != null) { | ||
| 133 | + throw exception(RECEIVABLE_PLAN_EXISTS_RECEIVABLE); | ||
| 134 | + } | ||
| 119 | } | 135 | } |
| 120 | - | ||
| 121 | } | 136 | } |
| 122 | 137 | ||
| 138 | + // TODO @puhui999:操作日志没记录上 | ||
| 123 | @Override | 139 | @Override |
| 124 | @Transactional(rollbackFor = Exception.class) | 140 | @Transactional(rollbackFor = Exception.class) |
| 125 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | 141 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", |
| @@ -127,6 +143,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -127,6 +143,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 127 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | 143 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 128 | public void updateReceivable(CrmReceivableSaveReqVO updateReqVO) { | 144 | public void updateReceivable(CrmReceivableSaveReqVO updateReqVO) { |
| 129 | Assert.notNull(updateReqVO.getId(), "回款编号不能为空"); | 145 | Assert.notNull(updateReqVO.getId(), "回款编号不能为空"); |
| 146 | + updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段 | ||
| 130 | // 1.1 校验存在 | 147 | // 1.1 校验存在 |
| 131 | CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId()); | 148 | CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId()); |
| 132 | // 1.2 只有草稿、审批中,可以编辑; | 149 | // 1.2 只有草稿、审批中,可以编辑; |
| @@ -135,7 +152,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -135,7 +152,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 135 | throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); | 152 | throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); |
| 136 | } | 153 | } |
| 137 | 154 | ||
| 138 | - // 2. 更新还款 | 155 | + // 2. 更新回款 |
| 139 | CrmReceivableDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivableDO.class); | 156 | CrmReceivableDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivableDO.class); |
| 140 | receivableMapper.updateById(updateObj); | 157 | receivableMapper.updateById(updateObj); |
| 141 | 158 | ||
| @@ -160,27 +177,25 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -160,27 +177,25 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 160 | receivableMapper.updateById(new CrmReceivableDO().setId(id).setAuditStatus(auditStatus)); | 177 | receivableMapper.updateById(new CrmReceivableDO().setId(id).setAuditStatus(auditStatus)); |
| 161 | } | 178 | } |
| 162 | 179 | ||
| 163 | - // TODO @liuhongfeng:缺一个取消回款的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum | ||
| 164 | - | ||
| 165 | @Override | 180 | @Override |
| 166 | @Transactional(rollbackFor = Exception.class) | 181 | @Transactional(rollbackFor = Exception.class) |
| 167 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_DELETE_SUB_TYPE, bizNo = "{{#id}}", | 182 | @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_DELETE_SUB_TYPE, bizNo = "{{#id}}", |
| 168 | success = CRM_RECEIVABLE_DELETE_SUCCESS) | 183 | success = CRM_RECEIVABLE_DELETE_SUCCESS) |
| 169 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | 184 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 170 | public void deleteReceivable(Long id) { | 185 | public void deleteReceivable(Long id) { |
| 171 | - // 校验存在 | 186 | + // 1.1 校验存在 |
| 172 | CrmReceivableDO receivable = validateReceivableExists(id); | 187 | CrmReceivableDO receivable = validateReceivableExists(id); |
| 173 | - // 如果被 CrmReceivablePlanDO 所使用,则不允许删除 | ||
| 174 | - if (Objects.nonNull(receivable.getPlanId()) && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) { | 188 | + // 1.2 如果被 CrmReceivablePlanDO 所使用,则不允许删除 |
| 189 | + if (receivable.getPlanId() != null && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) { | ||
| 175 | throw exception(RECEIVABLE_DELETE_FAIL); | 190 | throw exception(RECEIVABLE_DELETE_FAIL); |
| 176 | } | 191 | } |
| 177 | - // 删除 | ||
| 178 | - receivableMapper.deleteById(id); | ||
| 179 | 192 | ||
| 180 | - // 删除数据权限 | 193 | + // 2. 删除 |
| 194 | + receivableMapper.deleteById(id); | ||
| 195 | + // 3. 删除数据权限 | ||
| 181 | permissionService.deletePermission(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), id); | 196 | permissionService.deletePermission(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), id); |
| 182 | 197 | ||
| 183 | - // 记录操作日志上下文 | 198 | + // 4. 记录操作日志上下文 |
| 184 | LogRecordContext.putVariable("receivable", receivable); | 199 | LogRecordContext.putVariable("receivable", receivable); |
| 185 | } | 200 | } |
| 186 | 201 | ||
| @@ -197,7 +212,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -197,7 +212,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 197 | 212 | ||
| 198 | // 2. 创建回款审批流程实例 | 213 | // 2. 创建回款审批流程实例 |
| 199 | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() | 214 | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() |
| 200 | - .setProcessDefinitionKey(RECEIVABLE_APPROVE).setBusinessKey(String.valueOf(id))); | 215 | + .setProcessDefinitionKey(BPM_PROCESS_DEFINITION_KEY).setBusinessKey(String.valueOf(id))); |
| 201 | 216 | ||
| 202 | // 3. 更新回款工作流编号 | 217 | // 3. 更新回款工作流编号 |
| 203 | receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId) | 218 | receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId) |
| @@ -246,8 +261,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | @@ -246,8 +261,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||
| 246 | } | 261 | } |
| 247 | 262 | ||
| 248 | @Override | 263 | @Override |
| 249 | - public Long getReceivableCountByContractId(Long contractId) { | ||
| 250 | - return receivableMapper.selectCount(CrmReceivableDO::getContractId, contractId); | 264 | + public Map<Long, BigDecimal> getReceivablePriceMapByContractId(Collection<Long> contractIds) { |
| 265 | + return receivableMapper.selectReceivablePriceMapByContractId(contractIds); | ||
| 251 | } | 266 | } |
| 252 | 267 | ||
| 253 | } | 268 | } |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java
| @@ -20,7 +20,7 @@ public class CrmReceivableResultListener extends BpmProcessInstanceResultEventLi | @@ -20,7 +20,7 @@ public class CrmReceivableResultListener extends BpmProcessInstanceResultEventLi | ||
| 20 | 20 | ||
| 21 | @Override | 21 | @Override |
| 22 | public String getProcessDefinitionKey() { | 22 | public String getProcessDefinitionKey() { |
| 23 | - return CrmReceivableServiceImpl.RECEIVABLE_APPROVE; | 23 | + return CrmReceivableServiceImpl.BPM_PROCESS_DEFINITION_KEY; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |