Commit 3b379d8cc0097e34c10a2dda6afb66adf8830b85

Authored by YunaiV
2 parents 8266fb8f 22191e81

Merge branch 'develop' of https://gitee.com/puhui999/ruoyi-vue-pro into develop

# Conflicts:
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
Showing 13 changed files with 412 additions and 10 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsCustomerController.java
@@ -2,6 +2,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics; @@ -2,6 +2,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*; 4 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerAreaRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
5 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsCustomerService; 9 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsCustomerService;
6 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
7 import io.swagger.v3.oas.annotations.tags.Tag; 11 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -86,4 +90,32 @@ public class CrmStatisticsCustomerController { @@ -86,4 +90,32 @@ public class CrmStatisticsCustomerController {
86 90
87 // TODO dhb52:【成交周期分析】里,有按照员工(已实现)、地区(未实现)、产品(未实现),需要在看看哈;可以把 CustomerDealCycle 拆成 3 个 tab,员工客户成交周期分析、地区客户成交周期分析、产品客户成交周期分析; 91 // TODO dhb52:【成交周期分析】里,有按照员工(已实现)、地区(未实现)、产品(未实现),需要在看看哈;可以把 CustomerDealCycle 拆成 3 个 tab,员工客户成交周期分析、地区客户成交周期分析、产品客户成交周期分析;
88 92
  93 + @GetMapping("/get-customer-industry-summary")
  94 + @Operation(summary = "获取客户行业统计数据")
  95 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  96 + public CommonResult<List<CrmStatisticCustomerIndustryRespVO>> getCustomerIndustry(@Valid CrmStatisticsCustomerReqVO reqVO) {
  97 + return success(customerService.getCustomerIndustry(reqVO));
  98 + }
  99 +
  100 + @GetMapping("/get-customer-source-summary")
  101 + @Operation(summary = "获取客户来源统计数据")
  102 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  103 + public CommonResult<List<CrmStatisticCustomerSourceRespVO>> getCustomerSource(@Valid CrmStatisticsCustomerReqVO reqVO) {
  104 + return success(customerService.getCustomerSource(reqVO));
  105 + }
  106 +
  107 + @GetMapping("/get-customer-level-summary")
  108 + @Operation(summary = "获取客户级别统计数据")
  109 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  110 + public CommonResult<List<CrmStatisticCustomerLevelRespVO>> getCustomerLevel(@Valid CrmStatisticsCustomerReqVO reqVO) {
  111 + return success(customerService.getCustomerLevel(reqVO));
  112 + }
  113 +
  114 + @GetMapping("/get-customer-area-summary")
  115 + @Operation(summary = "获取客户地区统计数据")
  116 + @PreAuthorize("@ss.hasPermission('crm:statistics-customer:query')")
  117 + public CommonResult<List<CrmStatisticCustomerAreaRespVO>> getCustomerArea(@Valid CrmStatisticsCustomerReqVO reqVO) {
  118 + return success(customerService.getCustomerArea(reqVO));
  119 + }
  120 +
89 } 121 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerAreaRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户省份分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerAreaRespVO {
  9 +
  10 + @Schema(description = "省份编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  11 + private Integer areaId;
  12 + @Schema(description = "省份名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "浙江省")
  13 + private String areaName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "省份占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double areaPortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerIndustryRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户行业分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerIndustryRespVO {
  9 +
  10 + @Schema(description = "客户行业ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer industryId;
  12 + @Schema(description = "客户行业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String industryName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "行业占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double industryPortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerLevelRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户级别分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerLevelRespVO {
  9 +
  10 + @Schema(description = "客户级别ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer level;
  12 + @Schema(description = "客户级别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String levelName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "级别占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double levelPortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/analyze/CrmStatisticCustomerSourceRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - CRM 客户来源分析 VO")
  7 +@Data
  8 +public class CrmStatisticCustomerSourceRespVO {
  9 +
  10 + @Schema(description = "客户来源ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  11 + private Integer source;
  12 + @Schema(description = "客户来源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  13 + private String sourceName;
  14 +
  15 + @Schema(description = "客户个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Integer customerCount;
  17 +
  18 + @Schema(description = "成交个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Integer dealCount;
  20 +
  21 + @Schema(description = "来源占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + private Double sourcePortion;
  23 +
  24 + @Schema(description = "成交占比(%)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Double dealPortion;
  26 +
  27 +}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.statistics; 1 package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
2 2
3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*; 3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerAreaRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
4 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
5 9
6 import java.util.List; 10 import java.util.List;
@@ -41,4 +45,12 @@ public interface CrmStatisticsCustomerMapper { @@ -41,4 +45,12 @@ public interface CrmStatisticsCustomerMapper {
41 45
42 List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO); 46 List<CrmStatisticsCustomerDealCycleByUserRespVO> selectCustomerDealCycleGroupByUser(CrmStatisticsCustomerReqVO reqVO);
43 47
  48 + List<CrmStatisticCustomerIndustryRespVO> selectCustomerIndustryListGroupbyIndustryId(CrmStatisticsCustomerReqVO reqVO);
  49 +
  50 + List<CrmStatisticCustomerSourceRespVO> selectCustomerSourceListGroupbySource(CrmStatisticsCustomerReqVO reqVO);
  51 +
  52 + List<CrmStatisticCustomerLevelRespVO> selectCustomerLevelListGroupbyLevel(CrmStatisticsCustomerReqVO reqVO);
  53 +
  54 + List<CrmStatisticCustomerAreaRespVO> selectSummaryListByAreaId(CrmStatisticsCustomerReqVO reqVO);
  55 +
44 } 56 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java
1 package cn.iocoder.yudao.module.crm.service.statistics; 1 package cn.iocoder.yudao.module.crm.service.statistics;
2 2
3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*; 3 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerAreaRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
4 8
5 import java.util.List; 9 import java.util.List;
6 10
@@ -77,4 +81,36 @@ public interface CrmStatisticsCustomerService { @@ -77,4 +81,36 @@ public interface CrmStatisticsCustomerService {
77 */ 81 */
78 List<CrmStatisticsCustomerDealCycleByUserRespVO> getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO); 82 List<CrmStatisticsCustomerDealCycleByUserRespVO> getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO);
79 83
  84 + /**
  85 + * 获取客户行业统计数据
  86 + *
  87 + * @param reqVO 请求参数
  88 + * @return 统计数据
  89 + */
  90 + List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO);
  91 +
  92 + /**
  93 + * 获取客户来源统计数据
  94 + *
  95 + * @param reqVO 请求参数
  96 + * @return 统计数据
  97 + */
  98 + List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO);
  99 +
  100 + /**
  101 + * 获取客户级别统计数据
  102 + *
  103 + * @param reqVO 请求参数
  104 + * @return 统计数据
  105 + */
  106 + List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO);
  107 +
  108 + /**
  109 + * 获取客户地区统计数据
  110 + *
  111 + * @param reqVO 请求参数
  112 + * @return 统计数据
  113 + */
  114 + List<CrmStatisticCustomerAreaRespVO> getCustomerArea(CrmStatisticsCustomerReqVO reqVO);
  115 +
80 } 116 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
@@ -4,7 +4,14 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,14 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 5 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  7 +import cn.iocoder.yudao.framework.ip.core.Area;
  8 +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
  9 +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
7 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*; 10 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerAreaRespVO;
  12 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO;
  14 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO;
8 import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper; 15 import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper;
9 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 16 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
10 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 17 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -23,6 +30,8 @@ import java.util.stream.Stream; @@ -23,6 +30,8 @@ import java.util.stream.Stream;
23 30
24 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
25 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; 32 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
  34 +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*;
26 35
27 /** 36 /**
28 * CRM 客户分析 Service 实现类 37 * CRM 客户分析 Service 实现类
@@ -236,6 +245,104 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe @@ -236,6 +245,104 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
236 return summaryList; 245 return summaryList;
237 } 246 }
238 247
  248 + @Override
  249 + public List<CrmStatisticCustomerIndustryRespVO> getCustomerIndustry(CrmStatisticsCustomerReqVO reqVO) {
  250 + // 1. 获得用户编号数组
  251 + List<Long> userIds = getUserIds(reqVO);
  252 + if (CollUtil.isEmpty(userIds)) {
  253 + return Collections.emptyList();
  254 + }
  255 + reqVO.setUserIds(userIds);
  256 + // 2. 获取客户行业统计数据
  257 + List<CrmStatisticCustomerIndustryRespVO> industryRespVOList = customerMapper.selectCustomerIndustryListGroupbyIndustryId(reqVO);
  258 + if (CollUtil.isEmpty(industryRespVOList)) {
  259 + return Collections.emptyList();
  260 + }
  261 +
  262 + return convertList(industryRespVOList, item -> {
  263 + if (ObjUtil.isNull(item.getIndustryId())) {
  264 + return item;
  265 + }
  266 + item.setIndustryName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, item.getIndustryId()));
  267 + return item;
  268 + });
  269 + }
  270 +
  271 + @Override
  272 + public List<CrmStatisticCustomerSourceRespVO> getCustomerSource(CrmStatisticsCustomerReqVO reqVO) {
  273 + // 1. 获得用户编号数组
  274 + List<Long> userIds = getUserIds(reqVO);
  275 + if (CollUtil.isEmpty(userIds)) {
  276 + return Collections.emptyList();
  277 + }
  278 + reqVO.setUserIds(userIds);
  279 + // 2. 获取客户行业统计数据
  280 + List<CrmStatisticCustomerSourceRespVO> sourceRespVOList = customerMapper.selectCustomerSourceListGroupbySource(reqVO);
  281 + if (CollUtil.isEmpty(sourceRespVOList)) {
  282 + return Collections.emptyList();
  283 + }
  284 +
  285 + return convertList(sourceRespVOList, item -> {
  286 + if (ObjUtil.isNull(item.getSource())) {
  287 + return item;
  288 + }
  289 + item.setSourceName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_SOURCE, item.getSource()));
  290 + return item;
  291 + });
  292 + }
  293 +
  294 + @Override
  295 + public List<CrmStatisticCustomerLevelRespVO> getCustomerLevel(CrmStatisticsCustomerReqVO reqVO) {
  296 + // 1. 获得用户编号数组
  297 + List<Long> userIds = getUserIds(reqVO);
  298 + if (CollUtil.isEmpty(userIds)) {
  299 + return Collections.emptyList();
  300 + }
  301 + reqVO.setUserIds(userIds);
  302 + // 2. 获取客户行业统计数据
  303 + List<CrmStatisticCustomerLevelRespVO> levelRespVOList = customerMapper.selectCustomerLevelListGroupbyLevel(reqVO);
  304 + if (CollUtil.isEmpty(levelRespVOList)) {
  305 + return Collections.emptyList();
  306 + }
  307 +
  308 + return convertList(levelRespVOList, item -> {
  309 + if (ObjUtil.isNull(item.getLevel())) {
  310 + return item;
  311 + }
  312 + item.setLevelName(dictDataApi.getDictDataLabel(CRM_CUSTOMER_LEVEL, item.getLevel()));
  313 + return item;
  314 + });
  315 + }
  316 +
  317 + @Override
  318 + public List<CrmStatisticCustomerAreaRespVO> getCustomerArea(CrmStatisticsCustomerReqVO reqVO) {
  319 + // 1. 获得用户编号数组
  320 + List<Long> userIds = getUserIds(reqVO);
  321 + if (CollUtil.isEmpty(userIds)) {
  322 + return Collections.emptyList();
  323 + }
  324 + reqVO.setUserIds(userIds);
  325 + // 2. 获取客户地区统计数据
  326 + List<CrmStatisticCustomerAreaRespVO> list = customerMapper.selectSummaryListByAreaId(reqVO);
  327 + if (CollUtil.isEmpty(list)) {
  328 + return Collections.emptyList();
  329 + }
  330 +
  331 + // 拼接数据
  332 + List<Area> areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
  333 + areaList.add(new Area().setId(null).setName("未知"));
  334 + Map<Integer, Area> areaMap = convertMap(areaList, Area::getId);
  335 + List<CrmStatisticCustomerAreaRespVO> customerAreaRespVOList = convertList(list, item -> {
  336 + Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE);
  337 + if (parentId == null) {
  338 + return item;
  339 + }
  340 + findAndThen(areaMap, parentId, area -> item.setAreaId(parentId).setAreaName(area.getName()));
  341 + return item;
  342 + });
  343 + return customerAreaRespVOList;
  344 + }
  345 +
239 /** 346 /**
240 * 拼接用户信息(昵称) 347 * 拼接用户信息(昵称)
241 * 348 *
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
@@ -229,4 +229,89 @@ @@ -229,4 +229,89 @@
229 GROUP BY customer.owner_user_id 229 GROUP BY customer.owner_user_id
230 </select> 230 </select>
231 231
  232 + <select id="selectCustomerIndustryListGroupbyIndustryId"
  233 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerIndustryRespVO">
  234 + SELECT
  235 + industry_id,
  236 + COUNT(*) AS customerCount,
  237 + SUM(deal_status) AS dealCount,
  238 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS industryPortion,
  239 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  240 + FROM
  241 + crm_customer
  242 + WHERE
  243 + deleted = 0 AND industry_id IS NOT NULL
  244 + AND owner_user_id IN
  245 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  246 + #{userId}
  247 + </foreach>
  248 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  249 + #{times[1],javaType=java.time.LocalDateTime}
  250 + GROUP BY
  251 + industry_id;
  252 + </select>
  253 + <select id="selectCustomerSourceListGroupbySource"
  254 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerSourceRespVO">
  255 + SELECT
  256 + source,
  257 + COUNT(*) AS customerCount,
  258 + SUM(deal_status) AS dealCount,
  259 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS sourcePortion,
  260 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  261 + FROM
  262 + crm_customer
  263 + WHERE
  264 + deleted = 0 AND source IS NOT NULL
  265 + AND owner_user_id IN
  266 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  267 + #{userId}
  268 + </foreach>
  269 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  270 + #{times[1],javaType=java.time.LocalDateTime}
  271 + GROUP BY
  272 + source;
  273 + </select>
  274 + <select id="selectCustomerLevelListGroupbyLevel"
  275 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerLevelRespVO">
  276 + SELECT
  277 + level,
  278 + COUNT(*) AS customerCount,
  279 + SUM(deal_status) AS dealCount,
  280 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS levelPortion,
  281 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  282 + FROM
  283 + crm_customer
  284 + WHERE
  285 + deleted = 0 AND level IS NOT NULL
  286 + AND owner_user_id IN
  287 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  288 + #{userId}
  289 + </foreach>
  290 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  291 + #{times[1],javaType=java.time.LocalDateTime}
  292 + GROUP BY
  293 + level;
  294 + </select>
  295 + <select id="selectSummaryListByAreaId"
  296 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.analyze.CrmStatisticCustomerAreaRespVO">
  297 + SELECT
  298 + area_id,
  299 + COUNT(*) AS customerCount,
  300 + SUM(deal_status) AS dealCount,
  301 + ROUND(COUNT(*) / (SELECT COUNT(*) FROM crm_customer WHERE deleted = 0) * 100, 2) AS areaPortion,
  302 + ROUND(SUM(deal_status) / NULLIF(COUNT(*), 0) * 100, 2) AS dealPortion
  303 + FROM
  304 + crm_customer
  305 + WHERE
  306 + deleted = 0 AND area_id IS NOT NULL
  307 + AND owner_user_id IN
  308 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  309 + #{userId}
  310 + </foreach>
  311 + AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
  312 + #{times[1],javaType=java.time.LocalDateTime}
  313 + GROUP BY
  314 + area_id;
  315 + </select>
  316 +
232 </mapper> 317 </mapper>
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -624,7 +624,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -624,7 +624,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
624 throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY); 624 throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY);
625 } 625 }
626 // 1.3 支付价格不能为 0 626 // 1.3 支付价格不能为 0
627 - int newPayPrice = order.getPayPrice() + order.getAdjustPrice(); 627 + int newPayPrice = order.getPayPrice() + reqVO.getAdjustPrice();
628 if (newPayPrice <= 0) { 628 if (newPayPrice <= 0) {
629 throw exception(ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR); 629 throw exception(ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR);
630 } 630 }
@@ -635,12 +635,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -635,12 +635,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
635 635
636 // 3. 更新 TradeOrderItem,需要做 adjustPrice 的分摊 636 // 3. 更新 TradeOrderItem,需要做 adjustPrice 的分摊
637 List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); 637 List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
638 - List<Integer> dividePrices = TradePriceCalculatorHelper.dividePrice2(orderOrderItems, newPayPrice); 638 + List<Integer> dividePrices = TradePriceCalculatorHelper.dividePrice2(orderOrderItems, reqVO.getAdjustPrice());
639 List<TradeOrderItemDO> updateItems = new ArrayList<>(); 639 List<TradeOrderItemDO> updateItems = new ArrayList<>();
640 for (int i = 0; i < orderOrderItems.size(); i++) { 640 for (int i = 0; i < orderOrderItems.size(); i++) {
641 TradeOrderItemDO item = orderOrderItems.get(i); 641 TradeOrderItemDO item = orderOrderItems.get(i);
  642 + // TODO puhui999: 已有分摊记录的情况下价格是否会不对,也就是说之前订单项 1 分摊了 10 块这次是 -100
  643 + // 那么 setPayPrice 是否改为 (item.getPayPrice()-item.getAdjustPrice()) + dividePrices.get(i) 先减掉原来的价格再加上调价。经过验证可行,修改后订单价格增减都能正确分摊
642 updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(dividePrices.get(i)) 644 updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(dividePrices.get(i))
643 - .setPayPrice(item.getPayPrice() + dividePrices.get(i))); 645 + .setPayPrice((item.getPayPrice() - item.getAdjustPrice()) + dividePrices.get(i)));
644 } 646 }
645 tradeOrderItemMapper.updateBatch(updateItems); 647 tradeOrderItemMapper.updateBatch(updateItems);
646 648
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
@@ -254,12 +254,15 @@ public class TradePriceCalculatorHelper { @@ -254,12 +254,15 @@ public class TradePriceCalculatorHelper {
254 TradeOrderItemDO orderItem = items.get(i); 254 TradeOrderItemDO orderItem = items.get(i);
255 int partPrice; 255 int partPrice;
256 if (i < items.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 256 if (i < items.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减
257 - partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / total)); 257 + // partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / total));
  258 + // pr fix: 改为了使用订单原价来计算比例
  259 + partPrice = (int) (price * (1.0D * orderItem.getPrice() / total));
258 remainPrice -= partPrice; 260 remainPrice -= partPrice;
259 } else { 261 } else {
260 partPrice = remainPrice; 262 partPrice = remainPrice;
261 } 263 }
262 - Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); 264 + // TODO puhui999: 如果是减价的情况这里过不了
  265 + // Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0");
263 prices.add(partPrice); 266 prices.add(partPrice);
264 } 267 }
265 return prices; 268 return prices;
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java
1 package cn.iocoder.yudao.module.system.api.dict; 1 package cn.iocoder.yudao.module.system.api.dict;
2 2
  3 +import cn.hutool.core.util.ObjUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; 5 import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
4 6
5 import java.util.Collection; 7 import java.util.Collection;
@@ -34,6 +36,21 @@ public interface DictDataApi { @@ -34,6 +36,21 @@ public interface DictDataApi {
34 DictDataRespDTO getDictData(String type, String value); 36 DictDataRespDTO getDictData(String type, String value);
35 37
36 /** 38 /**
  39 + * 获得指定的字典标签,从缓存中
  40 + *
  41 + * @param type 字典类型
  42 + * @param value 字典数据值
  43 + * @return 字典标签
  44 + */
  45 + default String getDictDataLabel(String type, Integer value) {
  46 + DictDataRespDTO dictData = getDictData(type, String.valueOf(value));
  47 + if (ObjUtil.isNull(dictData)) {
  48 + return StrUtil.EMPTY;
  49 + }
  50 + return dictData.getLabel();
  51 + }
  52 +
  53 + /**
37 * 解析获得指定的字典数据,从缓存中 54 * 解析获得指定的字典数据,从缓存中
38 * 55 *
39 * @param type 字典类型 56 * @param type 字典类型
yudao-server/pom.xml
@@ -95,11 +95,11 @@ @@ -95,11 +95,11 @@
95 </dependency> 95 </dependency>
96 96
97 <!-- ERP 相关模块。默认注释,保证编译速度 --> 97 <!-- ERP 相关模块。默认注释,保证编译速度 -->
98 - <dependency>  
99 - <groupId>cn.iocoder.boot</groupId>  
100 - <artifactId>yudao-module-erp-biz</artifactId>  
101 - <version>${revision}</version>  
102 - </dependency> 98 +<!-- <dependency>-->
  99 +<!-- <groupId>cn.iocoder.boot</groupId>-->
  100 +<!-- <artifactId>yudao-module-erp-biz</artifactId>-->
  101 +<!-- <version>${revision}</version>-->
  102 +<!-- </dependency>-->
103 103
104 <!-- spring boot 配置所需依赖 --> 104 <!-- spring boot 配置所需依赖 -->
105 <dependency> 105 <dependency>