Jelajahi Sumber

✨ CRM:完善回款 plan 列表

YunaiV 1 tahun lalu
induk
melakukan
ba47402a7f

+ 1 - 0
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 {
         return success(contractService.getRemindContractCount(getLoginUserId()));
     }
 
+    // TODO @芋艿:需要看下;
     @GetMapping("/list-all-simple-by-customer")
     @Operation(summary = "获得合同精简列表", description = "只包含有读权限的客户的合同,主要用于前端的下拉选项")
     @Parameter(name = "customerId", description = "客户编号", required = true)

+ 29 - 24
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;
 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({

+ 15 - 5
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java

@@ -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;
 
 }

+ 0 - 48
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java

@@ -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;
-    }
-
-}

+ 1 - 1
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 {
      */
     private LocalDateTime returnTime;
     /**
-     * 回款类型
+     * 计划回款类型
      *
      * 枚举 {@link CrmReceivableReturnTypeEnum}
      */

+ 0 - 3
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
                 .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 - 0
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;
 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);
+    }
+
     /**
      * 获得合同分页
      *

+ 13 - 0
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;
 
 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);
+    }
+
     /**
      * 获得回款分页
      *