CRM:code review 客户总量统计

This commit is contained in:
YunaiV 2024-03-09 16:32:18 +08:00
parent 85817a2426
commit 8dcc12f215
8 changed files with 63 additions and 46 deletions

View File

@ -16,12 +16,12 @@
<module>yudao-module-system</module> <module>yudao-module-system</module>
<module>yudao-module-infra</module> <module>yudao-module-infra</module>
<!-- <module>yudao-module-member</module>--> <!-- <module>yudao-module-member</module>-->
<!-- <module>yudao-module-bpm</module>--> <module>yudao-module-bpm</module>
<!-- <module>yudao-module-report</module>--> <!-- <module>yudao-module-report</module>-->
<!-- <module>yudao-module-mp</module>--> <!-- <module>yudao-module-mp</module>-->
<!-- <module>yudao-module-pay</module>--> <!-- <module>yudao-module-pay</module>-->
<!-- <module>yudao-module-mall</module>--> <!-- <module>yudao-module-mall</module>-->
<!-- <module>yudao-module-crm</module>--> <module>yudao-module-crm</module>
<!-- <module>yudao-module-erp</module>--> <!-- <module>yudao-module-erp</module>-->
<!-- 示例项目 --> <!-- 示例项目 -->
<!-- <module>yudao-example</module>--> <!-- <module>yudao-example</module>-->

View File

@ -5,12 +5,14 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
/** /**
* 用户客户统计响应 Base VO * 用户客户统计响应 Base Response VO
*
* 目的可以统一拼接子 VO ownerUserIdownerUserName 属性
*/ */
@Data @Data
public class CrmStatisticsCustomerByUserBaseRespVO { public class CrmStatisticsCustomerByUserBaseRespVO {
@Schema(description = "负责人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@JsonIgnore @JsonIgnore
private Long ownerUserId; private Long ownerUserId;

View File

@ -5,13 +5,13 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
@Schema(description = "管理后台 - CRM 客户转化率分析 VO") @Schema(description = "管理后台 - CRM 客户转化率分析 VO")
@Data @Data
@ -43,14 +43,14 @@ public class CrmStatisticsCustomerContractSummaryRespVO {
@Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "外呼") @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "外呼")
private String sourceName; private String sourceName;
@Schema(description = "负责人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@JsonIgnore @JsonIgnore
private Long ownerUserId; private Long ownerUserId;
@Schema(description = "负责人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @Schema(description = "负责人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String ownerUserName; private String ownerUserName;
@Schema(description = "创建人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@JsonIgnore @JsonIgnore
private String creatorUserId; private String creatorUserId;

View File

@ -12,7 +12,7 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - CRM 数据统计 员工客户分析 Request VO") @Schema(description = "管理后台 - CRM 数据统计员工客户分析 Request VO")
@Data @Data
public class CrmStatisticsCustomerReqVO { public class CrmStatisticsCustomerReqVO {
@ -39,12 +39,16 @@ public class CrmStatisticsCustomerReqVO {
@NotEmpty(message = "时间范围不能为空") @NotEmpty(message = "时间范围不能为空")
private LocalDateTime[] times; private LocalDateTime[] times;
// TODO @dhb52这个时间间隔建议前端传递例如说字段叫 interval枚举有天季度因为一般分析类的系统都是交给用户选择筛选时间间隔而我们这里是默认根据日期选项默认对应的 interval 而已
// 然后实现上可以在 common 包的 enums 加个 DateIntervalEnum里面一个是 interval 字段枚举过去然后有个 pattern 字段用于格式化时间格式
// 这样的话可以通过 interval 获取到 pattern然后前端就可以根据 pattern 格式化时间计算还是交给数据库
/** /**
* group by DATE_FORMAT(field, #{dateFormat}) * group by DATE_FORMAT(field, #{dateFormat})
*/ */
@Schema(description = "Group By 日期格式", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "%Y%m") @Schema(description = "Group By 日期格式", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "%Y%m")
private String sqlDateFormat; private String sqlDateFormat;
// TODO @dhb52这个字段目前是不是没啥用呀
/** /**
* 数据类型 {@link CrmBizTypeEnum} * 数据类型 {@link CrmBizTypeEnum}
*/ */

View File

@ -13,17 +13,18 @@ import java.util.List;
@Mapper @Mapper
public interface CrmStatisticsCustomerMapper { public interface CrmStatisticsCustomerMapper {
List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); // TODO @dhb52拼写GroupBy一般 idea 如果出现绿色的警告可能是单词拼写错误建议是要修改的哈
List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerCreateCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); List<CrmStatisticsCustomerSummaryByDateRespVO> selectCustomerDealCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); // 已经 review
List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupbyUser(CrmStatisticsCustomerReqVO reqVO); List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerCreateCountGroupbyUser(CrmStatisticsCustomerReqVO reqVO); // 已经 review
List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); List<CrmStatisticsCustomerSummaryByUserRespVO> selectCustomerDealCountGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); List<CrmStatisticsCustomerSummaryByUserRespVO> selectContractPriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); List<CrmStatisticsCustomerSummaryByUserRespVO> selectReceivablePriceGroupbyUser(CrmStatisticsCustomerReqVO crmStatisticsCustomerReqVO); // 已经 review
List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupRecordCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO); List<CrmStatisticsFollowupSummaryByDateRespVO> selectFollowupRecordCountGroupbyDate(CrmStatisticsCustomerReqVO reqVO);

View File

@ -55,7 +55,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
@Resource @Resource
private DictDataApi dictDataApi; private DictDataApi dictDataApi;
@Override @Override
public List<CrmStatisticsCustomerSummaryByDateRespVO> getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO) { public List<CrmStatisticsCustomerSummaryByDateRespVO> getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO) {
// 1. 获得用户编号数组 // 1. 获得用户编号数组
@ -66,14 +65,17 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
reqVO.setUserIds(userIds); reqVO.setUserIds(userIds);
// 2. 获取分项统计数据 // 2. 获取分项统计数据
// TODO @dhb52如果是 list 变量要么 List 要么 s 后缀
reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1])); reqVO.setSqlDateFormat(getSqlDateFormat(reqVO.getTimes()[0], reqVO.getTimes()[1]));
final List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupbyDate(reqVO); final List<CrmStatisticsCustomerSummaryByDateRespVO> customerCreateCount = customerMapper.selectCustomerCreateCountGroupbyDate(reqVO);
final List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupbyDate(reqVO); final List<CrmStatisticsCustomerSummaryByDateRespVO> customerDealCount = customerMapper.selectCustomerDealCountGroupbyDate(reqVO);
// 3. 获取时间序列 // 3. 获取时间序列
// TODO @dhb523 4 其实做的是一类事情所以可以考虑 3.1 获取时间序列3.2 合并统计数据 这样注释然后中间就不空行了就是说一般空行的目的是让逻辑分片看着整体性更好但是不能让逻辑感觉碎碎的
final List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]); final List<String> times = generateTimeSeries(reqVO.getTimes()[0], reqVO.getTimes()[1]);
// 4. 合并统计数据 // 4. 合并统计数据
// TODO @dhb52这个是不是要 add respVoList 或者还可以 convertList(times, time -> new CrmStatisticsCustomerDealCycleByDateRespVO()...)
List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = new ArrayList<>(times.size()); List<CrmStatisticsCustomerSummaryByDateRespVO> respVoList = new ArrayList<>(times.size());
final Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCount, final Map<String, Integer> customerCreateCountMap = convertMap(customerCreateCount,
CrmStatisticsCustomerSummaryByDateRespVO::getTime, CrmStatisticsCustomerSummaryByDateRespVO::getTime,
@ -86,7 +88,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
.setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0)) .setCustomerCreateCount(customerCreateCountMap.getOrDefault(time, 0))
.setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0)) .setCustomerDealCount(customerDealCountMap.getOrDefault(time, 0))
)); ));
return respVoList; return respVoList;
} }
@ -131,7 +132,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
// 4. 拼接用户信息 // 4. 拼接用户信息
appendUserInfo(respVoList); appendUserInfo(respVoList);
return respVoList; return respVoList;
} }
@ -202,7 +202,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
// 4. 拼接用户信息 // 4. 拼接用户信息
appendUserInfo(respVoList); appendUserInfo(respVoList);
return respVoList; return respVoList;
} }
@ -290,7 +289,6 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time) new CrmStatisticsCustomerDealCycleByDateRespVO().setTime(time)
.setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D)) .setCustomerDealCycle(customerDealCycleMap.getOrDefault(time, 0D))
)); ));
return respVoList; return respVoList;
} }
@ -338,8 +336,7 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> respVoList) { private <T extends CrmStatisticsCustomerByUserBaseRespVO> void appendUserInfo(List<T> respVoList) {
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(respVoList, Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(respVoList,
CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId)); CrmStatisticsCustomerByUserBaseRespVO::getOwnerUserId));
respVoList.forEach(vo -> MapUtils.findAndThen(userMap, respVoList.forEach(vo -> MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())));
vo.getOwnerUserId(), user -> vo.setOwnerUserName(user.getNickname())));
} }
/** /**
@ -349,17 +346,18 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
* @return 用户编号数组 * @return 用户编号数组
*/ */
private List<Long> getUserIds(CrmStatisticsCustomerReqVO reqVO) { private List<Long> getUserIds(CrmStatisticsCustomerReqVO reqVO) {
// 情况一选中某个用户
if (ObjUtil.isNotNull(reqVO.getUserId())) { if (ObjUtil.isNotNull(reqVO.getUserId())) {
return List.of(reqVO.getUserId()); return List.of(reqVO.getUserId());
} else { }
// 1. 获得部门列表 // 情况二选中某个部门
// 2.1 获得部门列表
final Long deptId = reqVO.getDeptId(); final Long deptId = reqVO.getDeptId();
List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
deptIds.add(deptId); deptIds.add(deptId);
// 2. 获得用户编号 // 2.2 获得用户编号
return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId); return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
} }
}
/** /**
@ -380,6 +378,7 @@ public class CrmStatisticsCustomerServiceImpl implements CrmStatisticsCustomerSe
* @param endTime 结束时间 * @param endTime 结束时间
* @return 时间序列 * @return 时间序列
*/ */
// TODO @dhb52可以抽象到 DateUtils 开始时间结束时间事件间隔然后返回这个哈
private List<String> generateTimeSeries(LocalDateTime startTime, LocalDateTime endTime) { private List<String> generateTimeSeries(LocalDateTime startTime, LocalDateTime endTime) {
boolean byMonth = queryByMonth(startTime, endTime); boolean byMonth = queryByMonth(startTime, endTime);
List<String> times = CollUtil.newArrayList(); List<String> times = CollUtil.newArrayList();

View File

@ -2,11 +2,14 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper"> <mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsCustomerMapper">
<!-- TODO @dhb52数据库的关键字进行大写。例如说COUNT -->
<select id="selectCustomerCreateCountGroupbyDate" <select id="selectCustomerCreateCountGroupbyDate"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO">
SELECT SELECT
<!-- TODO @dhb52下面这个缩进一个 tab这样可读性更好哈 -->
DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time, DATE_FORMAT( create_time, #{sqlDateFormat} ) AS time,
count(*) AS customerCreateCount COUNT(*) AS customerCreateCount
FROM crm_customer FROM crm_customer
WHERE deleted = 0 WHERE deleted = 0
AND owner_user_id IN AND owner_user_id IN
@ -14,6 +17,7 @@
#{userId} #{userId}
</foreach> </foreach>
AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
<!-- TODO @dhb52这可以考虑不换行直接跟在后面的 AND更连贯哈 -->
#{times[1],javaType=java.time.LocalDateTime} #{times[1],javaType=java.time.LocalDateTime}
GROUP BY time GROUP BY time
</select> </select>
@ -21,6 +25,8 @@
<select id="selectCustomerDealCountGroupbyDate" <select id="selectCustomerDealCountGroupbyDate"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByDateRespVO">
SELECT SELECT
<!-- TODO @dhb52下面这个缩进一个 tab这样可读性更好哈 -->
<!-- TODO @dhb52表变量最好不要用 a、b可以用 customer 和 constract虽然长一点但是一眼看的清楚哈 -->
DATE_FORMAT( b.order_date, #{sqlDateFormat} ) AS time, DATE_FORMAT( b.order_date, #{sqlDateFormat} ) AS time,
count( DISTINCT a.id ) AS customerDealCount count( DISTINCT a.id ) AS customerDealCount
FROM crm_customer AS a FROM crm_customer AS a
@ -31,11 +37,13 @@
<foreach collection="userIds" item="userId" open="(" close=")" separator=","> <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
#{userId} #{userId}
</foreach> </foreach>
<!-- TODO @dhb52这个应该是 order_date 的范围哈;貌似如果改成这样,不需要查询 customer 表,只要 contract 表就 ok 拉 -->
AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND AND b.create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
#{times[1],javaType=java.time.LocalDateTime} #{times[1],javaType=java.time.LocalDateTime}
GROUP BY time GROUP BY time
</select> </select>
<!-- TODO @dhb52根据上面建议进行优化 -->
<select id="selectCustomerCreateCountGroupbyUser" <select id="selectCustomerCreateCountGroupbyUser"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
SELECT owner_user_id, COUNT(1) AS customer_create_count SELECT owner_user_id, COUNT(1) AS customer_create_count
@ -50,6 +58,7 @@
GROUP BY owner_user_id GROUP BY owner_user_id
</select> </select>
<!-- TODO @dhb52根据上面建议进行优化 -->
<select id="selectCustomerDealCountGroupbyUser" <select id="selectCustomerDealCountGroupbyUser"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
SELECT a.owner_user_id, count( DISTINCT a.id ) AS customer_deal_count SELECT a.owner_user_id, count( DISTINCT a.id ) AS customer_deal_count
@ -66,6 +75,7 @@
GROUP BY a.owner_user_id GROUP BY a.owner_user_id
</select> </select>
<!-- TODO @dhb52根据上面建议进行优化 -->
<select id="selectContractPriceGroupbyUser" <select id="selectContractPriceGroupbyUser"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
SELECT owner_user_id, IFNULL(SUM(total_price), 0) AS contract_price SELECT owner_user_id, IFNULL(SUM(total_price), 0) AS contract_price
@ -82,6 +92,7 @@
</select> </select>
<!-- TODO @dhb52根据上面建议进行优化 -->
<select id="selectReceivablePriceGroupbyUser" <select id="selectReceivablePriceGroupbyUser"
resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO"> resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.CrmStatisticsCustomerSummaryByUserRespVO">
SELECT owner_user_id, SELECT owner_user_id,

View File

@ -46,11 +46,11 @@
<!-- <version>${revision}</version>--> <!-- <version>${revision}</version>-->
<!-- </dependency>--> <!-- </dependency>-->
<!-- 工作流。默认注释,保证编译速度 --> <!-- 工作流。默认注释,保证编译速度 -->
<!-- <dependency>--> <dependency>
<!-- <groupId>cn.iocoder.boot</groupId>--> <groupId>cn.iocoder.boot</groupId>
<!-- <artifactId>yudao-module-bpm-biz</artifactId>--> <artifactId>yudao-module-bpm-biz</artifactId>
<!-- <version>${revision}</version>--> <version>${revision}</version>
<!-- </dependency>--> </dependency>
<!-- 支付服务。默认注释,保证编译速度 --> <!-- 支付服务。默认注释,保证编译速度 -->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>cn.iocoder.boot</groupId>--> <!-- <groupId>cn.iocoder.boot</groupId>-->
@ -88,18 +88,18 @@
<!-- </dependency>--> <!-- </dependency>-->
<!-- CRM 相关模块。默认注释,保证编译速度 --> <!-- CRM 相关模块。默认注释,保证编译速度 -->
<!-- <dependency>--> <dependency>
<!-- <groupId>cn.iocoder.boot</groupId>--> <groupId>cn.iocoder.boot</groupId>
<!-- <artifactId>yudao-module-crm-biz</artifactId>--> <artifactId>yudao-module-crm-biz</artifactId>
<!-- <version>${revision}</version>--> <version>${revision}</version>
<!-- </dependency>--> </dependency>
<!-- ERP 相关模块。默认注释,保证编译速度 --> <!-- ERP 相关模块。默认注释,保证编译速度 -->
<!-- <dependency>--> <dependency>
<!-- <groupId>cn.iocoder.boot</groupId>--> <groupId>cn.iocoder.boot</groupId>
<!-- <artifactId>yudao-module-erp-biz</artifactId>--> <artifactId>yudao-module-erp-biz</artifactId>
<!-- <version>${revision}</version>--> <version>${revision}</version>
<!-- </dependency>--> </dependency>
<!-- spring boot 配置所需依赖 --> <!-- spring boot 配置所需依赖 -->
<dependency> <dependency>