mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	✨ CRM:完善回款 plan 列表
This commit is contained in:
		| @@ -229,6 +229,7 @@ public class CrmContractController { | ||||
|         return success(contractService.getRemindContractCount(getLoginUserId())); | ||||
|     } | ||||
|  | ||||
|     // TODO @芋艿:需要看下; | ||||
|     @GetMapping("/list-all-simple-by-customer") | ||||
|     @Operation(summary = "获得合同精简列表", description = "只包含有读权限的客户的合同,主要用于前端的下拉选项") | ||||
|     @Parameter(name = "customerId", description = "客户编号", required = true) | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; | ||||
| import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | ||||
| @@ -34,6 +34,7 @@ import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Stream; | ||||
| @@ -42,6 +43,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||||
| import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | ||||
| import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||||
|  | ||||
| @@ -101,7 +103,7 @@ public class CrmReceivablePlanController { | ||||
|     @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | ||||
|     public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | ||||
|         PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); | ||||
|         return success(convertDetailReceivablePlanPage(pageResult)); | ||||
|         return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/page-by-customer") | ||||
| @@ -109,10 +111,9 @@ public class CrmReceivablePlanController { | ||||
|     public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { | ||||
|         Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | ||||
|         PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); | ||||
|         return success(convertDetailReceivablePlanPage(pageResult)); | ||||
|         return success(new PageResult<>(buildReceivableDetailList(pageResult.getList()), pageResult.getTotal())); | ||||
|     } | ||||
|  | ||||
|     // TODO 芋艿:后面在优化导出 | ||||
|     @GetMapping("/export-excel") | ||||
|     @Operation(summary = "导出回款计划 Excel") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") | ||||
| @@ -120,39 +121,42 @@ public class CrmReceivablePlanController { | ||||
|     public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, | ||||
|                                           HttpServletResponse response) throws IOException { | ||||
|         exportReqVO.setPageSize(PAGE_SIZE_NONE); | ||||
|         PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()); | ||||
|         List<CrmReceivablePlanDO> list = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()).getList(); | ||||
|         // 导出 Excel | ||||
|         ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, | ||||
|                 convertDetailReceivablePlanPage(pageResult).getList()); | ||||
|                 buildReceivableDetailList(list)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 构建详细的回款计划分页结果 | ||||
|      * | ||||
|      * @param pageResult 简单的回款计划分页结果 | ||||
|      * @return 详细的回款计划分页结果 | ||||
|      */ | ||||
|     private PageResult<CrmReceivablePlanRespVO> convertDetailReceivablePlanPage(PageResult<CrmReceivablePlanDO> pageResult) { | ||||
|         List<CrmReceivablePlanDO> receivablePlanList = pageResult.getList(); | ||||
|     private List<CrmReceivablePlanRespVO> buildReceivableDetailList(List<CrmReceivablePlanDO> receivablePlanList) { | ||||
|         if (CollUtil.isEmpty(receivablePlanList)) { | ||||
|             return PageResult.empty(pageResult.getTotal()); | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|         // 1. 获取客户列表 | ||||
|         List<CrmCustomerDO> customerList = customerService.getCustomerList( | ||||
|         // 1.1 获取客户 Map | ||||
|         Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap( | ||||
|                 convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); | ||||
|         // 2. 获取创建人、负责人列表 | ||||
|         // 1.2 获取创建人、负责人列表 | ||||
|         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList, | ||||
|                 contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); | ||||
|         // 3. 获得合同列表 | ||||
|         List<CrmContractDO> contractList = contractService.getContractList( | ||||
|         // 1.3 获得合同 Map | ||||
|         Map<Long, CrmContractDO> contractMap = contractService.getContractMap( | ||||
|                 convertSet(receivablePlanList, CrmReceivablePlanDO::getContractId)); | ||||
|         // 4. 获得还款列表 | ||||
|         List<CrmReceivableDO> receivableList = receivableService.getReceivableList( | ||||
|         // 1.4 获得还款 Map | ||||
|         Map<Long, CrmReceivableDO> receivableMap = receivableService.getReceivableMap( | ||||
|                 convertSet(receivablePlanList, CrmReceivablePlanDO::getReceivableId)); | ||||
|         return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); | ||||
|         // 2. 拼接数据 | ||||
|         return BeanUtils.toBean(receivablePlanList, CrmReceivablePlanRespVO.class, (receivablePlanVO) -> { | ||||
|             // 2.1 拼接客户信息 | ||||
|             findAndThen(customerMap, receivablePlanVO.getCustomerId(), customer -> receivablePlanVO.setCustomerName(customer.getName())); | ||||
|             // 2.2 拼接用户信息 | ||||
|             findAndThen(userMap, receivablePlanVO.getOwnerUserId(), user -> receivablePlanVO.setOwnerUserName(user.getNickname())); | ||||
|             findAndThen(userMap, Long.parseLong(receivablePlanVO.getCreator()), user -> receivablePlanVO.setCreatorName(user.getNickname())); | ||||
|             // 2.3 拼接合同信息 | ||||
|             findAndThen(contractMap, receivablePlanVO.getContractId(), contract -> receivablePlanVO.setContractNo(contract.getNo())); | ||||
|             // 2.4 拼接回款信息 | ||||
|             receivablePlanVO.setReceivable(BeanUtils.toBean(receivableMap.get(receivablePlanVO.getReceivableId()), CrmReceivableRespVO.class)); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @GetMapping("/remind-receivable-plan-count") | ||||
|     @Operation(summary = "获得待回款提醒数量") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") | ||||
| @@ -160,6 +164,7 @@ public class CrmReceivablePlanController { | ||||
|         return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId())); | ||||
|     } | ||||
|  | ||||
|     // TODO @芋艿:需要看下; | ||||
|     @GetMapping("/list-all-simple-by-customer") | ||||
|     @Operation(summary = "获得回款计划精简列表", description = "获得回款计划精简列表,主要用于前端的下拉选项") | ||||
|     @Parameters({ | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; | ||||
|  | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| @@ -35,14 +37,16 @@ public class CrmReceivablePlanRespVO { | ||||
|     @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") | ||||
|     private LocalDateTime returnTime; | ||||
|  | ||||
|     @Schema(description = "回款方式", example = "1") | ||||
|     private Integer returnType; // 来自 Receivable 的 returnType 字段 | ||||
|     @Schema(description = "计划回款方式", example = "1") | ||||
|     private Integer returnType; | ||||
|  | ||||
|     @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") | ||||
|     private BigDecimal price; | ||||
|  | ||||
|     @Schema(description = "回款编号", example = "19852") | ||||
|     private Long receivableId; | ||||
|     @Schema(description = "回款信息") | ||||
|     private CrmReceivableRespVO receivable; | ||||
|  | ||||
|     @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||||
|     private Boolean finishStatus; | ||||
| @@ -57,12 +61,18 @@ public class CrmReceivablePlanRespVO { | ||||
|     private String remark; | ||||
|  | ||||
|     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     @ExcelProperty("创建时间") | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
|     @Schema(description = "创建人", example = "25682") | ||||
|     private String creator; | ||||
|     @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     @ExcelProperty("更新时间") | ||||
|     private LocalDateTime updateTime; | ||||
|  | ||||
|     @Schema(description = "创建人名字", example = "test") | ||||
|     @Schema(description = "创建人", example = "1024") | ||||
|     @ExcelProperty("创建人") | ||||
|     private String creator; | ||||
|     @Schema(description = "创建人名字", example = "芋道源码") | ||||
|     @ExcelProperty("创建人名字") | ||||
|     private String creatorName; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,48 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.crm.convert.receivable; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.factory.Mappers; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||||
|  | ||||
| /** | ||||
|  * 回款计划 Convert | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Mapper | ||||
| public interface CrmReceivablePlanConvert { | ||||
|  | ||||
|     CrmReceivablePlanConvert INSTANCE = Mappers.getMapper(CrmReceivablePlanConvert.class); | ||||
|  | ||||
|     default PageResult<CrmReceivablePlanRespVO> convertPage(PageResult<CrmReceivablePlanDO> pageResult, Map<Long, AdminUserRespDTO> userMap, | ||||
|                                                             List<CrmCustomerDO> customerList, List<CrmContractDO> contractList, | ||||
|                                                             List<CrmReceivableDO> receivableList) { | ||||
|         PageResult<CrmReceivablePlanRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmReceivablePlanRespVO.class); | ||||
|         // 拼接关联字段 | ||||
|         Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId); | ||||
|         Map<Long, CrmContractDO> contractMap = convertMap(contractList, CrmContractDO::getId); | ||||
|         Map<Long, CrmReceivableDO> receivableMap = convertMap(receivableList, CrmReceivableDO::getId); | ||||
|         voPageResult.getList().forEach(receivablePlan -> { | ||||
|             findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname())); | ||||
|             findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); | ||||
|             findAndThen(customerMap, receivablePlan.getCustomerId(), customer -> receivablePlan.setCustomerName(customer.getName())); | ||||
|             findAndThen(contractMap, receivablePlan.getContractId(), contract -> receivablePlan.setContractNo(contract.getNo())); | ||||
|             findAndThen(receivableMap, receivablePlan.getReceivableId(), receivable -> receivablePlan.setReturnType(receivable.getReturnType())); | ||||
|         }); | ||||
|         return voPageResult; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -61,7 +61,7 @@ public class CrmReceivablePlanDO extends BaseDO { | ||||
|      */ | ||||
|     private LocalDateTime returnTime; | ||||
|     /** | ||||
|      * 回款类型 | ||||
|      * 计划回款类型 | ||||
|      * | ||||
|      * 枚举 {@link CrmReceivableReturnTypeEnum} | ||||
|      */ | ||||
|   | ||||
| @@ -47,7 +47,6 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||||
|                 .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) | ||||
|                 .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) | ||||
|                 .orderByDesc(CrmReceivablePlanDO::getPeriod); | ||||
|  | ||||
|         if (Objects.nonNull(pageReqVO.getContractNo())) { // 根据合同编号检索 | ||||
|             query.innerJoin(CrmContractDO.class, on -> on.like(CrmContractDO::getNo, pageReqVO.getContractNo()) | ||||
|                     .eq(CrmContractDO::getId, CrmReceivablePlanDO::getContractId)); | ||||
| @@ -67,9 +66,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||||
|         } else if (CrmReceivablePlanPageReqVO.REMIND_TYPE_RECEIVED.equals(pageReqVO.getRemindType())) { // 已回款 | ||||
|             query.isNotNull(CrmReceivablePlanDO::getReceivableId) | ||||
|                     .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); | ||||
|             ; | ||||
|         } | ||||
|  | ||||
|         return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,9 @@ import jakarta.validation.Valid; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||
|  | ||||
| /** | ||||
|  * CRM 合同 Service 接口 | ||||
| @@ -93,6 +96,16 @@ public interface CrmContractService { | ||||
|      */ | ||||
|     List<CrmContractDO> getContractList(Collection<Long> ids); | ||||
|  | ||||
|     /** | ||||
|      * 获得合同 Map | ||||
|      * | ||||
|      * @param ids 编号 | ||||
|      * @return 合同 Map | ||||
|      */ | ||||
|     default Map<Long, CrmContractDO> getContractMap(Collection<Long> ids) { | ||||
|         return convertMap(getContractList(ids), CrmContractDO::getId); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得合同分页 | ||||
|      * | ||||
|   | ||||
| @@ -9,6 +9,9 @@ import jakarta.validation.Valid; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||||
|  | ||||
| /** | ||||
|  * CRM 回款 Service 接口 | ||||
| @@ -71,6 +74,16 @@ public interface CrmReceivableService { | ||||
|      */ | ||||
|     List<CrmReceivableDO> getReceivableList(Collection<Long> ids); | ||||
|  | ||||
|     /** | ||||
|      * 获得回款 Map | ||||
|      * | ||||
|      * @param ids 编号 | ||||
|      * @return 回款 Map | ||||
|      */ | ||||
|     default Map<Long, CrmReceivableDO> getReceivableMap(Collection<Long> ids) { | ||||
|         return convertMap(getReceivableList(ids), CrmReceivableDO::getId); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得回款分页 | ||||
|      * | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV