CRM:完善回款 plan 列表

This commit is contained in:
YunaiV 2024-02-25 09:23:42 +08:00
parent 85c9524a2d
commit ba47402a7f
8 changed files with 72 additions and 81 deletions

View File

@ -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)

View File

@ -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({

View File

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

View File

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

View File

@ -61,7 +61,7 @@ public class CrmReceivablePlanDO extends BaseDO {
*/
private LocalDateTime returnTime;
/**
* 回款类型
* 计划回款类型
*
* 枚举 {@link CrmReceivableReturnTypeEnum}
*/

View File

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

View File

@ -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);
}
/**
* 获得合同分页
*

View File

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