mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	crm:code review 销售漏斗
This commit is contained in:
		| @@ -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(); | ||||
|         } | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
|  | ||||
| // TODO @puhui999:改成 CrmStatisticsBusinessSummaryByEndStatusRespVO,按照结束状态 | ||||
| @Schema(description = "管理后台 - CRM 商机结束状态统计 Response VO") | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 商机分页 | ||||
|      */ | ||||
|   | ||||
| @@ -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)) { | ||||
|   | ||||
| @@ -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()); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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> | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV