Forráskód Böngészése

crm:code review 销售漏斗

YunaiV 1 éve
szülő
commit
ed5f3a6bc2
13 módosított fájl, 38 hozzáadás és 82 törlés
  1. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
  2. 8 66
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsFunnelController.java
  3. 1 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticBusinessEndStatusRespVO.java
  4. 2 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelRespVO.java
  5. 1 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessRespVO.java
  6. 1 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java
  7. 2 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java
  8. 2 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
  9. 1 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
  10. 6 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
  11. 2 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
  12. 4 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java
  13. 7 6
      yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java

@@ -177,7 +177,7 @@ public class CrmBusinessController {
                 buildBusinessDetailList(list));
     }
 
-    private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
+    public List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
         if (CollUtil.isEmpty(list)) {
             return Collections.emptyList();
         }

+ 8 - 66
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsFunnelController.java

@@ -1,28 +1,16 @@
 package cn.iocoder.yudao.module.crm.controller.admin.statistics;
 
-import cn.hutool.core.collection.CollUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
-import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.business.CrmBusinessController;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticBusinessEndStatusRespVO;
 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticFunnelRespVO;
 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO;
 import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsFunnelReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
-import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
-import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
 import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsFunnelService;
-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 io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
@@ -33,14 +21,9 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 
 @Tag(name = "管理后台 - CRM 销售漏斗")
 @RestController
@@ -48,31 +31,20 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
 @Validated
 public class CrmStatisticsFunnelController {
 
+    // TODO @puhui999:crmStatisticsFunnelService 改成 funnelService 更好点哈
     @Resource
     private CrmStatisticsFunnelService crmStatisticsFunnelService;
-    @Resource
-    private CrmBusinessService businessService;
-    @Resource
-    private CrmCustomerService customerService;
-    @Resource
-    private CrmBusinessStatusService businessStatusTypeService;
-    @Resource
-    private CrmBusinessStatusService businessStatusService;
-
-    @Resource
-    private AdminUserApi adminUserApi;
-    @Resource
-    private DeptApi deptApi;
 
     @GetMapping("/get-funnel-summary")
-    @Operation(summary = "获取销售漏斗统计数据", description = "用于【销售漏斗】页面")
+    @Operation(summary = "获取销售漏斗统计数据", description = "用于【销售漏斗】页面的【销售漏斗分析】")
     @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')")
     public CommonResult<CrmStatisticFunnelRespVO> getFunnelSummary(@Valid CrmStatisticsFunnelReqVO reqVO) {
         return success(crmStatisticsFunnelService.getFunnelSummary(reqVO));
     }
 
+    // TODO @puhui:这个接口,应该是 getBusinessSummaryByEndStatus?这样更统一哈;
     @GetMapping("/get-business-end-status-summary")
-    @Operation(summary = "获取商机结束状态统计", description = "用于【销售漏斗】页面")
+    @Operation(summary = "获取商机结束状态统计", description = "用于【销售漏斗】页面的【销售漏斗分析】")
     @PreAuthorize("@ss.hasPermission('crm:statistics-funnel:query')")
     public CommonResult<List<CrmStatisticBusinessEndStatusRespVO>> getBusinessEndStatusSummary(@Valid CrmStatisticsFunnelReqVO reqVO) {
         return success(crmStatisticsFunnelService.getBusinessEndStatusSummary(reqVO));
@@ -86,7 +58,7 @@ public class CrmStatisticsFunnelController {
     }
 
     @GetMapping("/get-business-page-by-date")
-    @Operation(summary = "获得商机分页(按日期)", description = "用于【销售漏斗】页面")
+    @Operation(summary = "获得商机分页(按日期)", description = "用于【销售漏斗】页面的【新增商机分析】")
     @PreAuthorize("@ss.hasPermission('crm:business:query')")
     public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByDate(@Valid CrmStatisticsFunnelReqVO pageVO) {
         PageResult<CrmBusinessDO> pageResult = crmStatisticsFunnelService.getBusinessPageByDate(pageVO);
@@ -94,37 +66,7 @@ public class CrmStatisticsFunnelController {
     }
 
     private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
-        if (CollUtil.isEmpty(list)) {
-            return Collections.emptyList();
-        }
-        // 1.1 获取客户列表
-        Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
-                convertSet(list, CrmBusinessDO::getCustomerId));
-        // 1.2 获取创建人、负责人列表
-        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,
-                contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
-        // 1.3 获得商机状态组
-        Map<Long, CrmBusinessStatusTypeDO> statusTypeMap = businessStatusTypeService.getBusinessStatusTypeMap(
-                convertSet(list, CrmBusinessDO::getStatusTypeId));
-        Map<Long, CrmBusinessStatusDO> statusMap = businessStatusService.getBusinessStatusMap(
-                convertSet(list, CrmBusinessDO::getStatusId));
-        // 2. 拼接数据
-        return BeanUtils.toBean(list, CrmBusinessRespVO.class, businessVO -> {
-            // 2.1 设置客户名称
-            MapUtils.findAndThen(customerMap, businessVO.getCustomerId(), customer -> businessVO.setCustomerName(customer.getName()));
-            // 2.2 设置创建人、负责人名称
-            MapUtils.findAndThen(userMap, NumberUtils.parseLong(businessVO.getCreator()),
-                    user -> businessVO.setCreatorName(user.getNickname()));
-            MapUtils.findAndThen(userMap, businessVO.getOwnerUserId(), user -> {
-                businessVO.setOwnerUserName(user.getNickname());
-                MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> businessVO.setOwnerUserDeptName(dept.getName()));
-            });
-            // 2.3 设置商机状态
-            MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName()));
-            MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(
-                    businessService.getBusinessStatusName(businessVO.getEndStatus(), status)));
-        });
+        return SpringUtil.getBean(CrmBusinessController.class).buildBusinessDetailList(list);
     }
 
 }

+ 1 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticBusinessEndStatusRespVO.java

@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
 
 import java.math.BigDecimal;
 
+// TODO @puhui999:改成 CrmStatisticsBusinessSummaryByEndStatusRespVO,按照结束状态
 @Schema(description = "管理后台 - CRM 商机结束状态统计 Response VO")
 @NoArgsConstructor
 @AllArgsConstructor

+ 2 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelRespVO.java

@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+// TODO @puhui999:改成 CrmStatisticFunnelSummaryRespVO 更有统计的味道
 @Schema(description = "管理后台 - CRM 销售漏斗 Response VO")
 @NoArgsConstructor
 @AllArgsConstructor
@@ -17,6 +18,7 @@ public class CrmStatisticFunnelRespVO {
     @Schema(description = "商机数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long businessCount;
 
+    // TODO @puhui999:这个改成 businessWinCount 可能会更合适点哈;
     @Schema(description = "赢单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long winCount;
 

+ 1 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessRespVO.java

@@ -3,14 +3,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
 import lombok.Data;
-import lombok.NoArgsConstructor;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import java.util.List;
 
+// TODO @puhui999:是不是可以删除哈?
 @Schema(description = "管理后台 - CRM 商机 Response VO")
 @Data
 @ExcelIgnoreUnannotated

+ 1 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java

@@ -15,6 +15,7 @@ public class CrmStatisticsBusinessSummaryByDateRespVO {
     @Schema(description = "新增商机数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer businessCreateCount;
 
+    // TODO @puhui999:是不是金额哈,不是数量
     @Schema(description = "新增商机金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private BigDecimal businessDealCount;
 

+ 2 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java

@@ -17,6 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 
 @Schema(description = "管理后台 - CRM 销售漏斗 Request VO")
 @Data
+// TODO @puhui999:不用写 EqualsAndHashCode、ToString,已经全局 lombok 啦
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 public class CrmStatisticsFunnelReqVO extends PageParam {
@@ -42,6 +43,7 @@ public class CrmStatisticsFunnelReqVO extends PageParam {
     @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}")
     private Integer interval;
 
+    // TODO @puhui999:这个全部前端传递哈;参考 CrmStatisticsCustomerReqVO
     /**
      * 前端如果选择自定义时间, 那么前端传递起始-终止时间, 如果选择其他时间间隔类型, 则由后台计算起始-终止时间
      * 并作为参数传递给Mapper

+ 2 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java

@@ -73,6 +73,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
                 .betweenIfPresent(CrmBusinessDO::getCreateTime, times));
     }
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     default List<CrmBusinessDO> selectListByOwnerUserIdsAndEndStatusNotNull(Collection<Long> ownerUserIds, LocalDateTime[] times) {
         return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
                 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds)
@@ -80,6 +81,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
                 .isNotNull(CrmBusinessDO::getEndStatus));
     }
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     default List<CrmBusinessDO> selectListByOwnerUserIdsAndDate(Collection<Long> ownerUserIds, LocalDateTime[] times) {
         return selectList(new LambdaQueryWrapperX<CrmBusinessDO>()
                 .in(CrmBusinessDO::getOwnerUserId, ownerUserIds)

+ 1 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java

@@ -19,11 +19,9 @@ import org.apache.ibatis.annotations.Mapper;
 import org.springframework.lang.Nullable;
 import org.springframework.util.Assert;
 
-import javax.management.ObjectName;
 import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 
 /**
  * 客户 Mapper
@@ -188,6 +186,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
         return selectCount(query);
     }
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     default Long selectCountByOwnerUserIds(Collection<Long> ownerUserIds, LocalDateTime[] times){
         return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>()
                 .in(CrmCustomerDO::getOwnerUserId, ownerUserIds)

+ 6 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java

@@ -199,11 +199,12 @@ public interface CrmBusinessService {
      *
      * @param ownerUserIds 负责人编号
      * @param times        时间范围
-     * @param endStatus    商机结束状态
+     * @param endStatus    商机结束状态,允许为空
      * @return 商机数
      */
     Long getBusinessCountByOwnerUserIdsAndEndStatus(List<Long> ownerUserIds, LocalDateTime[] times, Integer endStatus);
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     /**
      * 获得商机列表【数据统计】
      *
@@ -213,6 +214,7 @@ public interface CrmBusinessService {
      */
     List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times);
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     /**
      * 获得商机列表【数据统计】
      *
@@ -223,10 +225,11 @@ public interface CrmBusinessService {
     List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times);
 
     /**
-     * 商机分页【数据统计】
+     * 获得商机分页,目前用于【数据统计】
+     *
      * @param ownerUserIds 负责人编号
      * @param times        时间范围
-     * @param pageNo       页码
+     * @param pageNo       页码 TODO @puhui999:直接传递 CrmStatisticsFunnelReqVO 吧,虽然有点耦合,但是更清晰一点;
      * @param pageSize     数量
      * @return 商机分页
      */

+ 2 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java

@@ -383,6 +383,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         return businessMapper.selectCountByOwnerUserIdsAndEndStatus(convertSet(ownerUserIds), times, endStatus);
     }
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     @Override
     public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndEndStatusNotNull(List<Long> ownerUserIds, LocalDateTime[] times) {
         if (CollUtil.isEmpty(ownerUserIds)) {
@@ -391,6 +392,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         return businessMapper.selectListByOwnerUserIdsAndEndStatusNotNull(convertSet(ownerUserIds), times);
     }
 
+    // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
     @Override
     public List<CrmBusinessDO> getBusinessListByOwnerUserIdsAndDate(List<Long> ownerUserIds, LocalDateTime[] times) {
         if (CollUtil.isEmpty(ownerUserIds)) {

+ 4 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java

@@ -51,6 +51,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
     @Resource
     private DeptApi deptApi;
 
+    // TODO @puhui999:貌似想了下,可能还是得按照;;;
     @Override
     public CrmStatisticFunnelRespVO getFunnelSummary(CrmStatisticsFunnelReqVO reqVO) {
         // 1. 获得用户编号数组
@@ -76,6 +77,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
             return Collections.emptyList();
         }
 
+        // TODO @puhui999:这个可以优化下,通过统计 sql,不通过内存计算;
         // 2.1 获得用户负责的商机
         List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndEndStatusNotNull(reqVO.getUserIds(), reqVO.getTimes());
         // 2.2 统计各阶段数据
@@ -99,6 +101,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
         }
 
         // 2. 按天统计,获取分项统计数据
+        // TODO @puhui999:可以这个统计,返回的时候,就把数量、金额一起统计好;
         List<CrmStatisticsBusinessSummaryByDateRespVO> businessCreateCountList = funnelMapper.selectBusinessCreateCountGroupByDate(reqVO);
         List<CrmBusinessDO> businessList = businessService.getBusinessListByOwnerUserIdsAndDate(reqVO.getUserIds(), reqVO.getTimes());
         Map<String, BigDecimal> businessDealCountMap = businessList.stream().collect(Collectors.groupingBy(business ->
@@ -128,7 +131,7 @@ public class CrmStatisticsFunnelServiceImpl implements CrmStatisticsFunnelServic
         if (CollUtil.isEmpty(pageVO.getUserIds())) {
             return PageResult.empty();
         }
-
+        // 2. 执行查询
         return businessService.getBusinessPageByDate(pageVO.getUserIds(), pageVO.getTimes(), pageVO.getPageNo(), pageVO.getPageSize());
     }
 

+ 7 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml

@@ -4,15 +4,16 @@
 
     <select id="selectBusinessCreateCountGroupByDate"
             resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.CrmStatisticsBusinessSummaryByDateRespVO">
-        SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS time, COUNT(*) AS businessCreateCount
+        SELECT
+            DATE_FORMAT(create_time, '%Y-%m-%d') AS time,
+            COUNT(*) AS businessCreateCount
         FROM crm_business
         WHERE deleted = 0
         AND owner_user_id IN
-        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
-            #{userId}
-        </foreach>
-        AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND
-        #{times[1],javaType=java.time.LocalDateTime}
+            <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+                #{userId}
+            </foreach>
+        AND create_time BETWEEN #{times[0],javaType=java.time.LocalDateTime} AND #{times[1],javaType=java.time.LocalDateTime}
         GROUP BY time
     </select>