package cn.iocoder.yudao.module.crm.api.report;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.module.crm.api.report.dto.CrmBusinessAnalyzeRespDTO;
|
import cn.iocoder.yudao.module.crm.api.report.dto.CrmContractAnalyzeRespDTO;
|
import cn.iocoder.yudao.module.crm.api.report.dto.CrmCustomerAnalyzeRespDTO;
|
import cn.iocoder.yudao.module.crm.api.report.dto.CrmSalesFunnelRespDTO;
|
import cn.iocoder.yudao.module.crm.api.report.dto.CrmSalesPerformanceRespDTO;
|
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
|
import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
|
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
|
import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService;
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import jakarta.annotation.Resource;
|
import org.springframework.context.annotation.Lazy;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.time.LocalDateTime;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
|
/**
|
* CRM 营销报表 API 实现类
|
*
|
* @author 芋道源码
|
*/
|
@RestController
|
@RequestMapping(CrmReportApi.PREFIX)
|
@Validated
|
public class CrmReportApiImpl implements CrmReportApi {
|
|
@Resource
|
private CrmCustomerMapper customerMapper;
|
@Resource
|
private CrmBusinessMapper businessMapper;
|
@Resource
|
private CrmContractMapper contractMapper;
|
@Resource
|
@Lazy // 延迟加载,避免循环依赖
|
private CrmReceivableService receivableService;
|
@Resource
|
private AdminUserApi adminUserApi;
|
@Resource
|
private DeptApi deptApi;
|
|
@Override
|
public CommonResult<CrmCustomerAnalyzeRespDTO> getCustomerAnalyze(LocalDateTime startTime, LocalDateTime endTime) {
|
CrmCustomerAnalyzeRespDTO result = new CrmCustomerAnalyzeRespDTO();
|
// 客户总数
|
result.setTotalCount(customerMapper.selectCount());
|
// 今日新增
|
result.setTodayCount(customerMapper.selectTodayCount());
|
// 成交客户数
|
result.setDealCount(customerMapper.selectDealCount());
|
// 成交率
|
if (result.getTotalCount() > 0) {
|
result.setDealRate(BigDecimal.valueOf(result.getDealCount())
|
.divide(BigDecimal.valueOf(result.getTotalCount()), 4, RoundingMode.HALF_UP)
|
.multiply(BigDecimal.valueOf(100)));
|
} else {
|
result.setDealRate(BigDecimal.ZERO);
|
}
|
// 锁定客户数
|
result.setLockCount(customerMapper.selectLockCount());
|
// 公海客户数
|
result.setPoolCount(customerMapper.selectPoolCount());
|
return success(result);
|
}
|
|
@Override
|
public CommonResult<CrmBusinessAnalyzeRespDTO> getBusinessAnalyze(LocalDateTime startTime, LocalDateTime endTime) {
|
CrmBusinessAnalyzeRespDTO result = new CrmBusinessAnalyzeRespDTO();
|
// 商机总数
|
result.setTotalCount(businessMapper.selectCount());
|
// 今日新增
|
result.setTodayCount(businessMapper.selectTodayCount());
|
// 商机总金额
|
result.setTotalPrice(businessMapper.selectTotalPriceSum());
|
// 成交商机数
|
result.setSuccessCount(businessMapper.selectSuccessCount());
|
// 成交商机金额
|
result.setSuccessPrice(businessMapper.selectSuccessPriceSum());
|
// 商机转化率
|
if (result.getTotalCount() > 0) {
|
result.setSuccessRate(BigDecimal.valueOf(result.getSuccessCount())
|
.divide(BigDecimal.valueOf(result.getTotalCount()), 4, RoundingMode.HALF_UP)
|
.multiply(BigDecimal.valueOf(100)));
|
} else {
|
result.setSuccessRate(BigDecimal.ZERO);
|
}
|
// 进行中商机数
|
result.setProcessingCount(businessMapper.selectProcessingCount());
|
// 失败商机数
|
result.setFailCount(businessMapper.selectFailCount());
|
return success(result);
|
}
|
|
@Override
|
public CommonResult<CrmContractAnalyzeRespDTO> getContractAnalyze(LocalDateTime startTime, LocalDateTime endTime) {
|
CrmContractAnalyzeRespDTO result = new CrmContractAnalyzeRespDTO();
|
// 合同总数
|
result.setTotalCount(contractMapper.selectCount());
|
// 今日新增
|
result.setTodayCount(contractMapper.selectTodayCount());
|
// 合同总金额
|
result.setTotalPrice(contractMapper.selectTotalPriceSum());
|
// 审批通过合同数
|
result.setApproveCount(contractMapper.selectApproveCount());
|
// 审批通过合同金额
|
result.setApprovePrice(contractMapper.selectApprovePriceSum());
|
// 审批中合同数
|
result.setProcessCount(contractMapper.selectProcessCount());
|
// 已回款金额
|
BigDecimal receivablePrice = receivableService.getReceivablePriceSum();
|
result.setReceivablePrice(receivablePrice != null ? receivablePrice : BigDecimal.ZERO);
|
// 回款率
|
if (result.getApprovePrice() != null && result.getApprovePrice().compareTo(BigDecimal.ZERO) > 0) {
|
result.setReceivableRate(result.getReceivablePrice()
|
.divide(result.getApprovePrice(), 4, RoundingMode.HALF_UP)
|
.multiply(BigDecimal.valueOf(100)));
|
} else {
|
result.setReceivableRate(BigDecimal.ZERO);
|
}
|
return success(result);
|
}
|
|
@Override
|
public CommonResult<CrmSalesFunnelRespDTO> getSalesFunnel() {
|
CrmSalesFunnelRespDTO result = new CrmSalesFunnelRespDTO();
|
List<CrmSalesFunnelRespDTO.FunnelStage> stages = new ArrayList<>();
|
|
// 阶段1:线索/客户
|
Long customerCount = customerMapper.selectCount();
|
stages.add(createStage("客户", customerCount, BigDecimal.ZERO));
|
|
// 阶段2:商机
|
Long businessCount = businessMapper.selectCount();
|
BigDecimal businessPrice = businessMapper.selectTotalPriceSum();
|
stages.add(createStage("商机", businessCount, businessPrice));
|
|
// 阶段3:合同
|
Long contractCount = contractMapper.selectApproveCount();
|
BigDecimal contractPrice = contractMapper.selectApprovePriceSum();
|
stages.add(createStage("合同", contractCount, contractPrice));
|
|
// 阶段4:回款
|
BigDecimal receivablePrice = receivableService.getReceivablePriceSum();
|
stages.add(createStage("回款", null, receivablePrice));
|
|
// 计算转化率
|
for (int i = 0; i < stages.size(); i++) {
|
if (i == 0) {
|
stages.get(i).setConversionRate(BigDecimal.valueOf(100));
|
} else if (customerCount > 0 && stages.get(i).getCount() != null) {
|
stages.get(i).setConversionRate(BigDecimal.valueOf(stages.get(i).getCount())
|
.divide(BigDecimal.valueOf(customerCount), 4, RoundingMode.HALF_UP)
|
.multiply(BigDecimal.valueOf(100)));
|
} else {
|
stages.get(i).setConversionRate(BigDecimal.ZERO);
|
}
|
}
|
|
result.setStages(stages);
|
return success(result);
|
}
|
|
@Override
|
public CommonResult<CrmSalesPerformanceRespDTO> getSalesPerformance(LocalDateTime startTime, LocalDateTime endTime) {
|
CrmSalesPerformanceRespDTO result = new CrmSalesPerformanceRespDTO();
|
List<CrmSalesPerformanceRespDTO.SalesItem> items = new ArrayList<>();
|
|
// 获取所有销售人员(有合同或商机的负责人)
|
List<Long> userIds = contractMapper.selectOwnerUserIds();
|
userIds.addAll(businessMapper.selectOwnerUserIds());
|
userIds = userIds.stream().distinct().collect(Collectors.toList());
|
|
if (CollUtil.isEmpty(userIds)) {
|
result.setItems(items);
|
return success(result);
|
}
|
|
// 获取用户信息
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
|
|
// 获取部门信息
|
List<Long> deptIds = userMap.values().stream()
|
.map(AdminUserRespDTO::getDeptId)
|
.filter(id -> id != null)
|
.distinct()
|
.collect(Collectors.toList());
|
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds);
|
|
for (Long userId : userIds) {
|
AdminUserRespDTO user = userMap.get(userId);
|
if (user == null) {
|
continue;
|
}
|
|
CrmSalesPerformanceRespDTO.SalesItem item = new CrmSalesPerformanceRespDTO.SalesItem();
|
item.setUserId(userId);
|
item.setUserName(user.getNickname());
|
// 获取部门名称
|
if (user.getDeptId() != null) {
|
DeptRespDTO dept = deptMap.get(user.getDeptId());
|
item.setDeptName(dept != null ? dept.getName() : "");
|
}
|
|
// 合同数量和金额
|
item.setContractCount(contractMapper.selectCountByOwnerUserId(userId));
|
item.setContractPrice(contractMapper.selectPriceSumByOwnerUserId(userId));
|
|
// 回款金额
|
item.setReceivablePrice(receivableService.getReceivablePriceByOwnerUserId(userId));
|
|
// 商机数量和金额
|
item.setBusinessCount(businessMapper.selectCountByOwnerUserId(userId));
|
item.setBusinessPrice(businessMapper.selectPriceSumByOwnerUserId(userId));
|
|
items.add(item);
|
}
|
|
result.setItems(items);
|
return success(result);
|
}
|
|
private CrmSalesFunnelRespDTO.FunnelStage createStage(String name, Long count, BigDecimal price) {
|
CrmSalesFunnelRespDTO.FunnelStage stage = new CrmSalesFunnelRespDTO.FunnelStage();
|
stage.setName(name);
|
stage.setCount(count);
|
stage.setPrice(price != null ? price : BigDecimal.ZERO);
|
return stage;
|
}
|
|
}
|