Commit 3b379d8cc0097e34c10a2dda6afb66adf8830b85
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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 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 | 9 | import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsCustomerService; |
| 6 | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 7 | 11 | import io.swagger.v3.oas.annotations.tags.Tag; |
| ... | ... | @@ -86,4 +90,32 @@ public class CrmStatisticsCustomerController { |
| 86 | 90 | |
| 87 | 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 | 1 | package cn.iocoder.yudao.module.crm.dal.mysql.statistics; |
| 2 | 2 | |
| 3 | 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 | import org.apache.ibatis.annotations.Mapper; |
| 5 | 9 | |
| 6 | 10 | import java.util.List; |
| ... | ... | @@ -41,4 +45,12 @@ public interface CrmStatisticsCustomerMapper { |
| 41 | 45 | |
| 42 | 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 | 1 | package cn.iocoder.yudao.module.crm.service.statistics; |
| 2 | 2 | |
| 3 | 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 | 9 | import java.util.List; |
| 6 | 10 | |
| ... | ... | @@ -77,4 +81,36 @@ public interface CrmStatisticsCustomerService { |
| 77 | 81 | */ |
| 78 | 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 | 4 | import cn.hutool.core.util.ObjUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 6 | 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 | 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 | 15 | import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper; |
| 9 | 16 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 10 | 17 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| ... | ... | @@ -23,6 +30,8 @@ import java.util.stream.Stream; |
| 23 | 30 | |
| 24 | 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 25 | 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 | 37 | * CRM 客户分析 Service 实现类 |
| ... | ... | @@ -236,6 +245,104 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe |
| 236 | 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 | 229 | GROUP BY customer.owner_user_id |
| 230 | 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 | 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 | 624 | throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY); |
| 625 | 625 | } |
| 626 | 626 | // 1.3 支付价格不能为 0 |
| 627 | - int newPayPrice = order.getPayPrice() + order.getAdjustPrice(); | |
| 627 | + int newPayPrice = order.getPayPrice() + reqVO.getAdjustPrice(); | |
| 628 | 628 | if (newPayPrice <= 0) { |
| 629 | 629 | throw exception(ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR); |
| 630 | 630 | } |
| ... | ... | @@ -635,12 +635,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 635 | 635 | |
| 636 | 636 | // 3. 更新 TradeOrderItem,需要做 adjustPrice 的分摊 |
| 637 | 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 | 639 | List<TradeOrderItemDO> updateItems = new ArrayList<>(); |
| 640 | 640 | for (int i = 0; i < orderOrderItems.size(); i++) { |
| 641 | 641 | TradeOrderItemDO item = orderOrderItems.get(i); |
| 642 | + // TODO puhui999: 已有分摊记录的情况下价格是否会不对,也就是说之前订单项 1 分摊了 10 块这次是 -100 | |
| 643 | + // 那么 setPayPrice 是否改为 (item.getPayPrice()-item.getAdjustPrice()) + dividePrices.get(i) 先减掉原来的价格再加上调价。经过验证可行,修改后订单价格增减都能正确分摊 | |
| 642 | 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 | 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 | 254 | TradeOrderItemDO orderItem = items.get(i); |
| 255 | 255 | int partPrice; |
| 256 | 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 | 260 | remainPrice -= partPrice; |
| 259 | 261 | } else { |
| 260 | 262 | partPrice = remainPrice; |
| 261 | 263 | } |
| 262 | - Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); | |
| 264 | + // TODO puhui999: 如果是减价的情况这里过不了 | |
| 265 | + // Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); | |
| 263 | 266 | prices.add(partPrice); |
| 264 | 267 | } |
| 265 | 268 | return prices; | ... | ... |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java
| 1 | 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 | 5 | import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; |
| 4 | 6 | |
| 5 | 7 | import java.util.Collection; |
| ... | ... | @@ -34,6 +36,21 @@ public interface DictDataApi { |
| 34 | 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 | 56 | * @param type 字典类型 | ... | ... |
yudao-server/pom.xml
| ... | ... | @@ -95,11 +95,11 @@ |
| 95 | 95 | </dependency> |
| 96 | 96 | |
| 97 | 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 | 104 | <!-- spring boot 配置所需依赖 --> |
| 105 | 105 | <dependency> | ... | ... |