Commit ba47402a7fa5a986fcc99aea2c4de5c57d16c67e
1 parent
85c9524a
✨ CRM:完善回款 plan 列表
Showing
8 changed files
with
72 additions
and
81 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
| ... | ... | @@ -229,6 +229,7 @@ public class CrmContractController { |
| 229 | 229 | return success(contractService.getRemindContractCount(getLoginUserId())); |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | + // TODO @芋艿:需要看下; | |
| 232 | 233 | @GetMapping("/list-all-simple-by-customer") |
| 233 | 234 | @Operation(summary = "获得合同精简列表", description = "只包含有读权限的客户的合同,主要用于前端的下拉选项") |
| 234 | 235 | @Parameter(name = "customerId", description = "客户编号", required = true) | ... | ... |
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 | 11 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; |
| 12 | 12 | import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; |
| 13 | 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 | 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 16 | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 17 | 17 | import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; |
| ... | ... | @@ -34,6 +34,7 @@ import org.springframework.validation.annotation.Validated; |
| 34 | 34 | import org.springframework.web.bind.annotation.*; |
| 35 | 35 | |
| 36 | 36 | import java.io.IOException; |
| 37 | +import java.util.Collections; | |
| 37 | 38 | import java.util.List; |
| 38 | 39 | import java.util.Map; |
| 39 | 40 | import java.util.stream.Stream; |
| ... | ... | @@ -42,6 +43,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 42 | 43 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 43 | 44 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; |
| 44 | 45 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | |
| 45 | 47 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 46 | 48 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 47 | 49 | |
| ... | ... | @@ -101,7 +103,7 @@ public class CrmReceivablePlanController { |
| 101 | 103 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| 102 | 104 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 103 | 105 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); |
| 104 | - return success(convertDetailReceivablePlanPage(pageResult)); | |
| 106 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); | |
| 105 | 107 | } |
| 106 | 108 | |
| 107 | 109 | @GetMapping("/page-by-customer") |
| ... | ... | @@ -109,10 +111,9 @@ public class CrmReceivablePlanController { |
| 109 | 111 | public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { |
| 110 | 112 | Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); |
| 111 | 113 | PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); |
| 112 | - return success(convertDetailReceivablePlanPage(pageResult)); | |
| 114 | + return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); | |
| 113 | 115 | } |
| 114 | 116 | |
| 115 | - // TODO 芋艿:后面在优化导出 | |
| 116 | 117 | @GetMapping("/export-excel") |
| 117 | 118 | @Operation(summary = "导出回款计划 Excel") |
| 118 | 119 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") |
| ... | ... | @@ -120,39 +121,42 @@ public class CrmReceivablePlanController { |
| 120 | 121 | public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, |
| 121 | 122 | HttpServletResponse response) throws IOException { |
| 122 | 123 | exportReqVO.setPageSize(PAGE_SIZE_NONE); |
| 123 | - PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()); | |
| 124 | + List<CrmReceivablePlanDO> list = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()).getList(); | |
| 124 | 125 | // 导出 Excel |
| 125 | 126 | ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, |
| 126 | - convertDetailReceivablePlanPage(pageResult).getList()); | |
| 127 | + buildReceivableDetailList(list)); | |
| 127 | 128 | } |
| 128 | 129 | |
| 129 | - /** | |
| 130 | - * 构建详细的回款计划分页结果 | |
| 131 | - * | |
| 132 | - * @param pageResult 简单的回款计划分页结果 | |
| 133 | - * @return 详细的回款计划分页结果 | |
| 134 | - */ | |
| 135 | - private PageResult<CrmReceivablePlanRespVO> convertDetailReceivablePlanPage(PageResult<CrmReceivablePlanDO> pageResult) { | |
| 136 | - List<CrmReceivablePlanDO> receivablePlanList = pageResult.getList(); | |
| 130 | + private List<CrmReceivablePlanRespVO> buildReceivableDetailList(List<CrmReceivablePlanDO> receivablePlanList) { | |
| 137 | 131 | if (CollUtil.isEmpty(receivablePlanList)) { |
| 138 | - return PageResult.empty(pageResult.getTotal()); | |
| 132 | + return Collections.emptyList(); | |
| 139 | 133 | } |
| 140 | - // 1. 获取客户列表 | |
| 141 | - List<CrmCustomerDO> customerList = customerService.getCustomerList( | |
| 134 | + // 1.1 获取客户 Map | |
| 135 | + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap( | |
| 142 | 136 | convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); |
| 143 | - // 2. 获取创建人、负责人列表 | |
| 137 | + // 1.2 获取创建人、负责人列表 | |
| 144 | 138 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList, |
| 145 | 139 | contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); |
| 146 | - // 3. 获得合同列表 | |
| 147 | - List<CrmContractDO> contractList = contractService.getContractList( | |
| 140 | + // 1.3 获得合同 Map | |
| 141 | + Map<Long, CrmContractDO> contractMap = contractService.getContractMap( | |
| 148 | 142 | convertSet(receivablePlanList, CrmReceivablePlanDO::getContractId)); |
| 149 | - // 4. 获得还款列表 | |
| 150 | - List<CrmReceivableDO> receivableList = receivableService.getReceivableList( | |
| 143 | + // 1.4 获得还款 Map | |
| 144 | + Map<Long, CrmReceivableDO> receivableMap = receivableService.getReceivableMap( | |
| 151 | 145 | convertSet(receivablePlanList, CrmReceivablePlanDO::getReceivableId)); |
| 152 | - return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); | |
| 146 | + // 2. 拼接数据 | |
| 147 | + return BeanUtils.toBean(receivablePlanList, CrmReceivablePlanRespVO.class, (receivablePlanVO) -> { | |
| 148 | + // 2.1 拼接客户信息 | |
| 149 | + findAndThen(customerMap, receivablePlanVO.getCustomerId(), customer -> receivablePlanVO.setCustomerName(customer.getName())); | |
| 150 | + // 2.2 拼接用户信息 | |
| 151 | + findAndThen(userMap, receivablePlanVO.getOwnerUserId(), user -> receivablePlanVO.setOwnerUserName(user.getNickname())); | |
| 152 | + findAndThen(userMap, Long.parseLong(receivablePlanVO.getCreator()), user -> receivablePlanVO.setCreatorName(user.getNickname())); | |
| 153 | + // 2.3 拼接合同信息 | |
| 154 | + findAndThen(contractMap, receivablePlanVO.getContractId(), contract -> receivablePlanVO.setContractNo(contract.getNo())); | |
| 155 | + // 2.4 拼接回款信息 | |
| 156 | + receivablePlanVO.setReceivable(BeanUtils.toBean(receivableMap.get(receivablePlanVO.getReceivableId()), CrmReceivableRespVO.class)); | |
| 157 | + }); | |
| 153 | 158 | } |
| 154 | 159 | |
| 155 | - | |
| 156 | 160 | @GetMapping("/remind-receivable-plan-count") |
| 157 | 161 | @Operation(summary = "获得待回款提醒数量") |
| 158 | 162 | @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") |
| ... | ... | @@ -160,6 +164,7 @@ public class CrmReceivablePlanController { |
| 160 | 164 | return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId())); |
| 161 | 165 | } |
| 162 | 166 | |
| 167 | + // TODO @芋艿:需要看下; | |
| 163 | 168 | @GetMapping("/list-all-simple-by-customer") |
| 164 | 169 | @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项") |
| 165 | 170 | @Parameters({ | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java
| 1 | 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 | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 6 | import lombok.Data; |
| 5 | 7 | |
| ... | ... | @@ -35,14 +37,16 @@ public class CrmReceivablePlanRespVO { |
| 35 | 37 | @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") |
| 36 | 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 | 43 | @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") |
| 42 | 44 | private BigDecimal price; |
| 43 | 45 | |
| 44 | 46 | @Schema(description = "回款编号", example = "19852") |
| 45 | 47 | private Long receivableId; |
| 48 | + @Schema(description = "回款信息") | |
| 49 | + private CrmReceivableRespVO receivable; | |
| 46 | 50 | |
| 47 | 51 | @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") |
| 48 | 52 | private Boolean finishStatus; |
| ... | ... | @@ -57,12 +61,18 @@ public class CrmReceivablePlanRespVO { |
| 57 | 61 | private String remark; |
| 58 | 62 | |
| 59 | 63 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 64 | + @ExcelProperty("创建时间") | |
| 60 | 65 | private LocalDateTime createTime; |
| 61 | 66 | |
| 62 | - @Schema(description = "创建人", example = "25682") | |
| 63 | - private String creator; | |
| 67 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 68 | + @ExcelProperty("更新时间") | |
| 69 | + private LocalDateTime updateTime; | |
| 64 | 70 | |
| 65 | - @Schema(description = "创建人名字", example = "test") | |
| 71 | + @Schema(description = "创建人", example = "1024") | |
| 72 | + @ExcelProperty("创建人") | |
| 73 | + private String creator; | |
| 74 | + @Schema(description = "创建人名字", example = "芋道源码") | |
| 75 | + @ExcelProperty("创建人名字") | |
| 66 | 76 | private String creatorName; |
| 67 | 77 | |
| 68 | 78 | } | ... | ... |
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/CrmReceivablePlanDO.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
| ... | ... | @@ -47,7 +47,6 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO |
| 47 | 47 | .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) |
| 48 | 48 | .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) |
| 49 | 49 | .orderByDesc(CrmReceivablePlanDO::getPeriod); |
| 50 | - | |
| 51 | 50 | if (Objects.nonNull(pageReqVO.getContractNo())) { // 根据合同编号检索 |
| 52 | 51 | query.innerJoin(CrmContractDO.class, on -> on.like(CrmContractDO::getNo, pageReqVO.getContractNo()) |
| 53 | 52 | .eq(CrmContractDO::getId, CrmReceivablePlanDO::getContractId)); |
| ... | ... | @@ -67,9 +66,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO |
| 67 | 66 | } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款 |
| 68 | 67 | query.isNotNull(CrmReceivablePlanDO::getReceivableId) |
| 69 | 68 | .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); |
| 70 | - ; | |
| 71 | 69 | } |
| 72 | - | |
| 73 | 70 | return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); |
| 74 | 71 | } |
| 75 | 72 | ... | ... |
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 | 13 | import java.time.LocalDateTime; |
| 14 | 14 | import java.util.Collection; |
| 15 | 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 | 21 | * CRM 合同 Service 接口 |
| ... | ... | @@ -94,6 +97,16 @@ public interface CrmContractService { |
| 94 | 97 | List<CrmContractDO> getContractList(Collection<Long> ids); |
| 95 | 98 | |
| 96 | 99 | /** |
| 100 | + * 获得合同 Map | |
| 101 | + * | |
| 102 | + * @param ids 编号 | |
| 103 | + * @return 合同 Map | |
| 104 | + */ | |
| 105 | + default Map<Long, CrmContractDO> getContractMap(Collection<Long> ids) { | |
| 106 | + return convertMap(getContractList(ids), CrmContractDO::getId); | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 97 | 110 | * 获得合同分页 |
| 98 | 111 | * |
| 99 | 112 | * 数据权限:基于 {@link CrmContractDO} 读取 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
| ... | ... | @@ -9,6 +9,9 @@ import jakarta.validation.Valid; |
| 9 | 9 | |
| 10 | 10 | import java.util.Collection; |
| 11 | 11 | import java.util.List; |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 12 | 15 | |
| 13 | 16 | /** |
| 14 | 17 | * CRM 回款 Service 接口 |
| ... | ... | @@ -72,6 +75,16 @@ public interface CrmReceivableService { |
| 72 | 75 | List<CrmReceivableDO> getReceivableList(Collection<Long> ids); |
| 73 | 76 | |
| 74 | 77 | /** |
| 78 | + * 获得回款 Map | |
| 79 | + * | |
| 80 | + * @param ids 编号 | |
| 81 | + * @return 回款 Map | |
| 82 | + */ | |
| 83 | + default Map<Long, CrmReceivableDO> getReceivableMap(Collection<Long> ids) { | |
| 84 | + return convertMap(getReceivableList(ids), CrmReceivableDO::getId); | |
| 85 | + } | |
| 86 | + | |
| 87 | + /** | |
| 75 | 88 | * 获得回款分页 |
| 76 | 89 | * |
| 77 | 90 | * 数据权限:基于 {@link CrmReceivableDO} 读取 | ... | ... |