diff --git a/easyink-admin/src/main/java/com/easyink/web/controller/wecom/StatisticsController.java b/easyink-admin/src/main/java/com/easyink/web/controller/wecom/StatisticsController.java index c90e390bbe95f29bac43e43ac656f90afaac0b17..3f11b87864ef07b73d9a62bf6eb39a86e4012127 100644 --- a/easyink-admin/src/main/java/com/easyink/web/controller/wecom/StatisticsController.java +++ b/easyink-admin/src/main/java/com/easyink/web/controller/wecom/StatisticsController.java @@ -1,19 +1,26 @@ package com.easyink.web.controller.wecom; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.easyink.common.core.controller.BaseController; import com.easyink.common.core.domain.AjaxResult; import com.easyink.common.core.page.TableDataInfo; import com.easyink.common.enums.ResultTip; import com.easyink.common.utils.PageInfoUtil; import com.easyink.wecom.domain.dto.statistics.*; +import com.easyink.wecom.domain.entity.WeUserCustomerMessageStatistics; import com.easyink.wecom.domain.vo.statistics.*; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeDateVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeUserVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeVO; import com.easyink.wecom.login.util.LoginTokenService; import com.easyink.wecom.service.*; +import com.easyink.wecom.service.statistic.WeEmpleCodeStatisticService; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -35,11 +42,12 @@ public class StatisticsController extends BaseController { private final WeUserService weUserService; private final PageHomeService pageHomeService; private final WeTagService weTagService; - private final WeGroupTagService weGroupTagService; + private final WeEmpleCodeStatisticService weEmpleCodeStatisticService; @GetMapping("/data") @ApiOperation("执行对应日期的数据统计任务,执行前需先将we_user_customer_message_statisticsService表中对应日期的数据删除。") + @Transactional public AjaxResult getData(String time) { String corpId = LoginTokenService.getLoginUser().getCorpId(); weUserService.getUserBehaviorDataByCorpId(corpId, time); @@ -233,4 +241,59 @@ public class StatisticsController extends BaseController { return AjaxResult.success(weGroupTagService.exportGroupTags(weTagStatisticsDTO)); } + @PostMapping("/emplecode/total") + @ApiOperation("活码统计-数据总览") + public AjaxResult listEmpleTotal(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + return AjaxResult.success(weEmpleCodeStatisticService.listEmpleTotal(dto)); + } + + @PostMapping("/emplecode/user/list") + @ApiOperation("活码统计-员工维度") + public TableDataInfo listEmpleUser(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + startPage(); + List list = weEmpleCodeStatisticService.listEmpleUser(dto); + return getDataTable(list); + } + + @PreAuthorize("@ss.hasPermi('stastistic:codeStatistics:export')") + @PostMapping("/emplecode/user/export") + @ApiOperation("活码统计-员工维度-导出报表") + public AjaxResult exportEmpleUser(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + return AjaxResult.success(weEmpleCodeStatisticService.exportEmpleUser(dto)); + } + + @PostMapping("/emplecode/emple/list") + @ApiOperation(("活码统计-活码维度")) + public TableDataInfo listEmple(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + startPage(); + List list = weEmpleCodeStatisticService.listEmple(dto); + return getDataTable(list); + } + + @PreAuthorize("@ss.hasPermi('stastistic:codeStatistics:export')") + @PostMapping("/emplecode/emple/export") + @ApiOperation("活码统计-活码维度-导出报表") + public AjaxResult exportEmple(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + return AjaxResult.success(weEmpleCodeStatisticService.exportEmple(dto)); + } + + @PostMapping("/emplecode/date/list") + @ApiOperation(("活码统计-日期维度")) + public TableDataInfo listEmpleDate(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + return getDataTable(weEmpleCodeStatisticService.listEmpleDate(dto)); + } + + @PreAuthorize("@ss.hasPermi('stastistic:codeStatistics:export')") + @PostMapping("/emplecode/date/export") + @ApiOperation("活码统计-日期维度-导出报表") + public AjaxResult exportEmpleDate(@RequestBody EmpleCodeStatisticDTO dto) { + dto.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + return AjaxResult.success(weEmpleCodeStatisticService.exportEmpleDate(dto)); + } } diff --git a/easyink-admin/src/main/java/com/easyink/web/controller/wecom/WeEmpleCodeController.java b/easyink-admin/src/main/java/com/easyink/web/controller/wecom/WeEmpleCodeController.java index d3792d7ac95e9b6597c2fce88f8b1db02c88584e..affc321119a51e0fdbe9fe5e27e5c1445c01567e 100644 --- a/easyink-admin/src/main/java/com/easyink/web/controller/wecom/WeEmpleCodeController.java +++ b/easyink-admin/src/main/java/com/easyink/web/controller/wecom/WeEmpleCodeController.java @@ -18,6 +18,7 @@ import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeAnalyseDTO; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeDTO; import com.easyink.wecom.domain.vo.WeEmpleCodeVO; import com.easyink.wecom.domain.vo.WeEmplyCodeScopeUserVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeByNameVO; import com.easyink.wecom.login.util.LoginTokenService; import com.easyink.wecom.service.WeEmpleCodeAnalyseService; import com.easyink.wecom.service.WeEmpleCodeService; @@ -84,6 +85,15 @@ public class WeEmpleCodeController extends BaseController { return getDataTable(list); } + @GetMapping("/listByName") + @ApiOperation("活码统计-根据名称模糊搜索活码信息") + public TableDataInfo listByName(FindWeEmpleCodeDTO weEmpleCode) { + weEmpleCode.setCorpId(LoginTokenService.getLoginUser().getCorpId()); + startPage(); + List list = weEmpleCodeService.listByName(weEmpleCode); + return getDataTable(list); + } + @PreAuthorize("@ss.hasPermi('wecom:code:query')") @GetMapping(value = "/{id}") diff --git a/easyink-common/src/main/java/com/easyink/common/constant/Constants.java b/easyink-common/src/main/java/com/easyink/common/constant/Constants.java index 05882cc649da2001a65f2ca85fd43569c99404aa..5e4756e2de28cf61e40fd12bfc3cd0722a54d507 100644 --- a/easyink-common/src/main/java/com/easyink/common/constant/Constants.java +++ b/easyink-common/src/main/java/com/easyink/common/constant/Constants.java @@ -240,7 +240,7 @@ public class Constants { /** * 初始化的菜单权限的菜单ID */ - protected static final Long[] INIT_MENU_LIST = new Long[]{2016L, 2014L, 2015L, 2022L, 2074L, 2020L, 2021L, 2002L, 2003L, 2001L, 2079L, 2080L, 2312L, 2313L, 2314L, 2315L, 2320L}; + protected static final Long[] INIT_MENU_LIST = new Long[]{2016L, 2014L, 2015L, 2022L, 2074L, 2020L, 2021L, 2002L, 2003L, 2001L, 2079L, 2080L, 2312L, 2313L, 2314L, 2315L, 2320L, 2327L, 2328L}; /** * 获取初始化菜单权限的菜单ID diff --git a/easyink-common/src/main/java/com/easyink/common/constant/UserConstants.java b/easyink-common/src/main/java/com/easyink/common/constant/UserConstants.java index 9bf39d574f99f92e47432c2a2a3fbff5b058985f..c26127f7ddbb1f80ea9c1c3cf746932468980a45 100644 --- a/easyink-common/src/main/java/com/easyink/common/constant/UserConstants.java +++ b/easyink-common/src/main/java/com/easyink/common/constant/UserConstants.java @@ -138,15 +138,15 @@ public class UserConstants { /** * 初始化的管理员默认所有菜单id */ - public static final String ADMIN_DEFAULT_MENU_IDS = "1,2,101,102,108,109,110,111,112,500,501,1009,1010,1011,1014,1015,1016,1018,1019,1020,1041,1044,1048,1050,1051,1052,1053,1054,2001,2002,2003,2004,2005,2006,2007,2010,2013,2014,2015,2016,2020,2021,2022,2023,2024,2025,2026,2028,2029,2051,2052,2053,2056,2060,2062,2071,2072,2073,2074,2076,2079,2080,2081,2082,2083,2084,2085,2086,2100,2101,2102,2105,2106,2107,2120,2124,2127,2131,2133,2134,2135,2138,2139,2141,2142,2151,2152,2153,2156,2157,2158,2159,2160,2163,2164,2165,2166,2179,2188,2189,2196,2201,2205,2206,2207,2208,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2221,2222,2223,2224,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2245,2247,2248,2249,2250,2251,2252,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2292,2293,2296,2297,2298,2299,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326"; + public static final String ADMIN_DEFAULT_MENU_IDS = "1,2,101,102,108,109,110,111,112,500,501,1009,1010,1011,1014,1015,1016,1018,1019,1020,1041,1044,1048,1050,1051,1052,1053,1054,2001,2002,2003,2004,2005,2006,2007,2010,2013,2014,2015,2016,2020,2021,2022,2023,2024,2025,2026,2028,2029,2051,2052,2053,2056,2060,2062,2071,2072,2073,2074,2076,2079,2080,2081,2082,2083,2084,2085,2086,2100,2101,2102,2105,2106,2107,2120,2124,2127,2131,2133,2134,2135,2138,2139,2141,2142,2151,2152,2153,2156,2157,2158,2159,2160,2163,2164,2165,2166,2179,2188,2189,2196,2201,2205,2206,2207,2208,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2221,2222,2223,2224,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2245,2247,2248,2249,2250,2251,2252,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2292,2293,2296,2297,2298,2299,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329"; /** * 初始化的部门管理员默认的所有菜单id */ - public static final String DEPARTMENT_ADMIN_DEFAULT_IDS = "1,1018,1019,1020,2001,2002,2003,2004,2005,2006,2007,2013,2014,2015,2016,2020,2021,2022,2023,2024,2025,2026,2028,2029,2052,2053,2056,2060,2062,2074,2079,2080,2081,2082,2083,2084,2085,2086,2100,2101,2102,2105,2106,2107,2120,2124,2127,2131,2133,2134,2135,2138,2139,2141,2142,2151,2152,2153,2156,2157,2158,2160,2163,2164,2179,2188,2201,2205,2206,2207,2208,2210,2211,2212,2213,2214,2215,2217,2218,2219,2221,2222,2223,2224,2236,2238,2243,2245,2247,2248,2250,2251,2252,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2272,2273,2274,2275,2276,2277,2280,2282,2283,2285,2286,2287,2288,2289,2292,2293,2296,2297,2298,2299,2302,2303,2304,2305,2306,2307,2308,2309,2311,2312,2313,2314,2315,2316,2317,2318,2320,2321,2322,2323,2324,2325,2326"; + public static final String DEPARTMENT_ADMIN_DEFAULT_IDS = "1,1018,1019,1020,2001,2002,2003,2004,2005,2006,2007,2013,2014,2015,2016,2020,2021,2022,2023,2024,2025,2026,2028,2029,2052,2053,2056,2060,2062,2074,2079,2080,2081,2082,2083,2084,2085,2086,2100,2101,2102,2105,2106,2107,2120,2124,2127,2131,2133,2134,2135,2138,2139,2141,2142,2151,2152,2153,2156,2157,2158,2160,2163,2164,2179,2188,2201,2205,2206,2207,2208,2210,2211,2212,2213,2214,2215,2217,2218,2219,2221,2222,2223,2224,2236,2238,2243,2245,2247,2248,2250,2251,2252,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2272,2273,2274,2275,2276,2277,2280,2282,2283,2285,2286,2287,2288,2289,2292,2293,2296,2297,2298,2299,2302,2303,2304,2305,2306,2307,2308,2309,2311,2312,2313,2314,2315,2316,2317,2318,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329"; /** * 初始化的员工默认的所有菜单id */ - public static final String EMPLOYEE_DEFAULT_IDS = "2001,2002,2003,2006,2007,2014,2015,2016,2020,2021,2022,2028,2074,2079,2080,2105,2106,2107,2160,2163,2164,2188,2224,2236,2243,2280,2062,2282,2299,2304,2308,2309,2312,2313,2314,2315,2320"; + public static final String EMPLOYEE_DEFAULT_IDS = "2001,2002,2003,2006,2007,2014,2015,2016,2020,2021,2022,2028,2074,2079,2080,2105,2106,2107,2160,2163,2164,2188,2224,2236,2243,2280,2062,2282,2299,2304,2308,2309,2312,2313,2314,2315,2320,2327,2328"; /** * 三方应用需要屏蔽的菜单 */ diff --git a/easyink-common/src/main/java/com/easyink/common/utils/DateUtils.java b/easyink-common/src/main/java/com/easyink/common/utils/DateUtils.java index ee14cbe261f7381513b44dd9042555a71527733b..3e2b23f603d268b9a95edb62a6fee9998b3e7384 100644 --- a/easyink-common/src/main/java/com/easyink/common/utils/DateUtils.java +++ b/easyink-common/src/main/java/com/easyink/common/utils/DateUtils.java @@ -11,6 +11,7 @@ import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -663,4 +664,31 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { } return inputTime.compareTo(getNowDate()) > 0; } + + /** + * 获取当前时间前一个小时的日期 + * + * @return 日期 格式为 YYYY-MM-DD + */ + public static String getBeforeHourDate() { + // 获取当前时间 + LocalDateTime currentTime = LocalDateTime.now(); + // 获取当前时间前一个小时的时间 + LocalDateTime oneHourAgo = currentTime.minusHours(1); + // 定义日期格式 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD); + // 将时间按照指定格式转换为字符串 + return oneHourAgo.format(formatter); + } + + /** + * 获取当前时间前一天的日期 + * + * @return 日期 格式为:YYYY-MM-DD + */ + public static String getYesterdayDateBeforeNow() { + LocalDate yesterday = LocalDate.now().minusDays(1); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD); + return yesterday.format(formatter); + } } diff --git a/easyink-quartz/src/main/java/com/easyink/quartz/task/DataStatisticsTask.java b/easyink-quartz/src/main/java/com/easyink/quartz/task/DataStatisticsTask.java index e50b5fd38b2f8c9a344bad048a5fcbdf10fa904b..b2d3a3a8da6c24aac81e89cb43a32291cc84ddfe 100644 --- a/easyink-quartz/src/main/java/com/easyink/quartz/task/DataStatisticsTask.java +++ b/easyink-quartz/src/main/java/com/easyink/quartz/task/DataStatisticsTask.java @@ -1,11 +1,11 @@ package com.easyink.quartz.task; -import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.easyink.common.core.domain.entity.WeCorpAccount; import com.easyink.common.utils.DateUtils; +import com.easyink.wecom.domain.entity.WeUserCustomerMessageStatistics; import com.easyink.wecom.service.WeCorpAccountService; import com.easyink.wecom.service.WeUserCustomerMessageStatisticsService; -import com.easyink.wecom.service.WeUserService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -36,6 +36,7 @@ public class DataStatisticsTask { weCorpAccountList.parallelStream().forEach(weCorpAccount -> { try { if (weCorpAccount != null && StringUtils.isNotBlank(weCorpAccount.getCorpId())) { + // 开始统计 userCustomerMessageStatisticsService.getMessageStatistics(weCorpAccount.getCorpId(), DateUtils.dateTime(DateUtils.getYesterday(DateUtils.getNowDate()))); } } catch (Exception e) { diff --git a/easyink-quartz/src/main/java/com/easyink/quartz/task/EmpleStatisticTask.java b/easyink-quartz/src/main/java/com/easyink/quartz/task/EmpleStatisticTask.java new file mode 100644 index 0000000000000000000000000000000000000000..0d33bc67aa00c0f8176d97b2a09cadb650ce9a5f --- /dev/null +++ b/easyink-quartz/src/main/java/com/easyink/quartz/task/EmpleStatisticTask.java @@ -0,0 +1,96 @@ +package com.easyink.quartz.task; + +import com.easyink.common.core.domain.entity.WeCorpAccount; +import com.easyink.common.utils.DateUtils; +import com.easyink.common.utils.ExceptionUtil; +import com.easyink.common.utils.StringUtils; +import com.easyink.common.utils.sql.BatchInsertUtil; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; +import com.easyink.wecom.mapper.statistic.WeEmpleCodeStatisticMapper; +import com.easyink.wecom.service.WeCorpAccountService; +import com.easyink.wecom.service.WeEmpleCodeAnalyseService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 活码统计-定时统计任务 + * + * @author lichaoyu + * @date 2023/7/7 13:48 + */ +@Slf4j +@Component("EmpleStatisticTask") +public class EmpleStatisticTask { + + private final WeEmpleCodeAnalyseService weEmpleCodeAnalyseService; + private final WeEmpleCodeStatisticMapper weEmpleCodeStatisticMapper; + private final WeCorpAccountService weCorpAccountService; + + + public EmpleStatisticTask(WeEmpleCodeAnalyseService weEmpleCodeAnalyseService, WeEmpleCodeStatisticMapper weEmpleCodeStatisticMapper, WeCorpAccountService weCorpAccountService) { + this.weEmpleCodeAnalyseService = weEmpleCodeAnalyseService; + this.weEmpleCodeStatisticMapper = weEmpleCodeStatisticMapper; + this.weCorpAccountService = weCorpAccountService; + } + + /** + * 活码统计-小时定时任务 + * + */ + public void getEmpleStatisticData() { + // 获取当前时间前一小时的日期 + String beforeHourDate = DateUtils.getBeforeHourDate(); + // 处理对应日期下的统计数据 + handleDateData(beforeHourDate); + } + + /** + * 活码统计-每日定时统计任务 + * + * @param date 日期 格式为YYYY-MM-DD,当传入时,统计对应日期下的活码数据,不传默认前一天的数据 + */ + public void getEmpleStatisticDateData(String date) { + String realDate; + if (StringUtils.EMPTY.equals(date)) { + realDate = DateUtils.getYesterdayDateBeforeNow(); + } else { + realDate = date; + } + // 处理对应日期下的统计数据 + handleDateData(realDate); + } + + /** + * 处理对应日期下的统计数据 + * + * @param date 日期 格式为YYYY-MM-DD + */ + private void handleDateData(String date) { + if (StringUtils.isBlank(date)) { + return; + } + List weCorpAccountList = weCorpAccountService.listOfAuthCorpInternalWeCorpAccount(); + // 统计每个企业下,活码统计表的数据 + weCorpAccountList.forEach(weCorpAccount -> { + try { + if (weCorpAccount != null && StringUtils.isNotBlank(weCorpAccount.getCorpId())) { + log.info("[活码统计] 活码统计定时任务开始执行--------> corpId:{}, date:{}", weCorpAccount.getCorpId(), date); + // 获取当前企业下所有有新增数据的活码-员工对应的统计数据 + List todayData = weEmpleCodeAnalyseService.getEmpleStatisticData(weCorpAccount.getCorpId(), date); + if (CollectionUtils.isEmpty(todayData)) { + return; + } + // 分批批量插入或更新今天的数据 + BatchInsertUtil.doInsert(todayData, list -> weEmpleCodeStatisticMapper.batchInsertOrUpdate(todayData)); + } + } catch (Exception e) { + log.info("[活码统计] 活码统计定时任务执行异常, corpId:{}, date:{}, ex:{}", weCorpAccount.getCorpId(), date, ExceptionUtil.getExceptionMessage(e)); + } finally { + log.info("[活码统计] 活码统计定时任务执行完成--------> corpId:{}, date:{}", weCorpAccount.getCorpId(), date); + } + }); + } +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/WeEmpleCodeStatistic.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/WeEmpleCodeStatistic.java new file mode 100644 index 0000000000000000000000000000000000000000..2df9b0f9fc9ca61f219ca11cbee8410090eb88d4 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/WeEmpleCodeStatistic.java @@ -0,0 +1,92 @@ +package com.easyink.wecom.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * 活码统计表实体类 + * + * @author lichaoyu + * @date 2023/7/5 13:44 + */ +@Data +@TableName("we_emple_code_statistic") +@NoArgsConstructor +@ApiModel("活码统计") +public class WeEmpleCodeStatistic { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId + @TableField("id") + private Long id; + + @ApiModelProperty("企业id") + @TableField("corp_id") + private String corpId; + + @ApiModelProperty("活码id") + @TableField("emple_code_id") + private Long empleCodeId; + + @ApiModelProperty("员工id") + @TableField("user_id") + private String userId; + + @ApiModelProperty("累计客户数") + @TableField("accumulate_customer_cnt") + private Integer accumulateCustomerCnt; + + @ApiModelProperty("留存客户数") + @TableField("retain_customer_cnt") + private Integer retainCustomerCnt; + + @ApiModelProperty("新增客户数") + @TableField("new_customer_cnt") + private Integer newCustomerCnt; + + @ApiModelProperty("流失客户数") + @TableField("loss_customer_cnt") + private Integer lossCustomerCnt; + + @ApiModelProperty("日期") + @TableField("time") + private String time; + + /** + * 用于初始化默认数据构造 + * + * @param corpId 企业ID + * @param empleCodeId 活码ID + * @param userId 员工ID + * @param time 日期,格式为YYYY-MM-DD + */ + public WeEmpleCodeStatistic(String corpId, Long empleCodeId, String userId, String time) { + this.corpId = corpId; + this.empleCodeId = empleCodeId; + this.userId = userId; + this.time = time; + accumulateCustomerCnt = 0; + retainCustomerCnt = 0; + newCustomerCnt = 0; + lossCustomerCnt = 0; + } + + /** + * 添加回调数据处理方法 + */ + public void addHandle() { + this.accumulateCustomerCnt++; + this.retainCustomerCnt++; + this.newCustomerCnt++; + } + + +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/dto/statistics/EmpleCodeStatisticDTO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/dto/statistics/EmpleCodeStatisticDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..c510c32d390c90bca37b78f773b85998eab8fbee --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/dto/statistics/EmpleCodeStatisticDTO.java @@ -0,0 +1,38 @@ +package com.easyink.wecom.domain.dto.statistics; + +import com.easyink.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * 活码统计-查询DTO + * + * @author lichaoyu + * @date 2023/7/4 10:01 + */ +@Data +public class EmpleCodeStatisticDTO extends BaseEntity { + + @ApiModelProperty("企业ID") + private String corpId; + + @ApiModelProperty("员工活码idList") + private List empleCodeIdList; + + @ApiModelProperty("部门idList") + private List departmentIds; + + @ApiModelProperty("员工idList") + private List userIds; + + @ApiModelProperty("当前时间 格式: YYYY-MM-DD HH:MM:SS") + private String nowTime; + + @ApiModelProperty("开始时间 格式: YYYY-MM-DD") + private String beginDate; + + @ApiModelProperty("结束时间 格式: YYYY-MM-DD") + private String endDate; +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/entity/WeUserCustomerMessageStatistics.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/entity/WeUserCustomerMessageStatistics.java index bfb6be1bf3d29a5ccfddd56e8da6d8b5cba6659e..c65e702583ab7f1b514b7cbfacc5e3cab39d93a2 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/domain/entity/WeUserCustomerMessageStatistics.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/entity/WeUserCustomerMessageStatistics.java @@ -69,6 +69,7 @@ public class WeUserCustomerMessageStatistics implements Serializable { private Boolean repliedWithinThirtyMinCustomerFlag; @ApiModelProperty(value = "当天员工主动发起会话次数") + @TableField(exist = false) private Integer userActiveChatCnt; } diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeBaseVO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeBaseVO.java new file mode 100644 index 0000000000000000000000000000000000000000..e5f6312c462ac76f3d8773a1e58071d2811d7d35 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeBaseVO.java @@ -0,0 +1,93 @@ +package com.easyink.wecom.domain.vo.statistics.emplecode; + +import com.easyink.common.annotation.Excel; +import com.easyink.common.constant.GenConstants; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 活码统计-基类VO + * + * @author lichaoyu + * @date 2023/7/4 10:08 + */ +@Data +@NoArgsConstructor +public class EmpleCodeBaseVO { + + @ApiModelProperty("累计添加客户") + @Excel(name = "累计添加客户", sort = 2) + private Integer accumulateCustomerCnt = 0; + + @ApiModelProperty("留存客户总数") + @Excel(name = "留存客户总数", sort = 3) + private Integer retainCustomerCnt = 0; + + @ApiModelProperty("新增客户数") + @Excel(name = "新增客户数", sort = 4) + private Integer newCustomerCnt = 0; + + @ApiModelProperty("流失客户数") + @Excel(name = "流失客户数", sort = 5) + private Integer lossCustomerCnt = 0; + + @ApiModelProperty("截止当前时间,新增客户数") + private Integer currentNewCustomerCnt = 0; + + @ApiModelProperty("新客留存率") + @Excel(name = "新客留存率", sort = 6) + private String retainNewCustomerRate; + + /** + * 留存率为空时返回的值 + */ + private final String NULL_VALUE = "-"; + + + /** + * 新客留存率 公式:截止当前时间,新增客户数 / 新增客户数 + */ + public String getRetainNewCustomerRate() { + if (currentNewCustomerCnt == null || newCustomerCnt == null) { + return NULL_VALUE; + } + BigDecimal percent = new BigDecimal(100); + if(newCustomerCnt == 0) { + return NULL_VALUE; + } + // 百分比 + BigDecimal currCntDecimal = new BigDecimal(currentNewCustomerCnt); + BigDecimal newCntDecimal = new BigDecimal(newCustomerCnt); + int scale = 2; + // 计算留存率 截止当前时间,新增客户数 / 新客数 + return currCntDecimal + .multiply(percent) + .divide(newCntDecimal, scale, RoundingMode.HALF_UP) + .stripTrailingZeros().toPlainString(); + } + + /** + * 绑定导出数据 + * 导出框架不能直接使用get方法获取属性值 + */ + public void bindExportData() { + if (newCustomerCnt == 0) { + retainNewCustomerRate = NULL_VALUE; + } else { + retainNewCustomerRate = getRetainNewCustomerRate() + GenConstants.PERCENT; + } + } + + public EmpleCodeBaseVO(Integer accumulateCustomerCnt, Integer retainCustomerCnt, Integer newCustomerCnt, Integer lossCustomerCnt, Integer currentNewCustomerCnt) { + this.accumulateCustomerCnt = accumulateCustomerCnt; + this.retainCustomerCnt = retainCustomerCnt; + this.newCustomerCnt = newCustomerCnt; + this.lossCustomerCnt = lossCustomerCnt; + this.currentNewCustomerCnt = currentNewCustomerCnt; + this.retainNewCustomerRate = getRetainNewCustomerRate(); + } +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeByNameVO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeByNameVO.java new file mode 100644 index 0000000000000000000000000000000000000000..5292231c57daec704b34790bfc1e62c018564b26 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeByNameVO.java @@ -0,0 +1,20 @@ +package com.easyink.wecom.domain.vo.statistics.emplecode; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 活码统计-根据活动场景获取活码信息VO + * + * @author lichaoyu + * @date 2023/7/4 17:48 + */ +@Data +public class EmpleCodeByNameVO { + + @ApiModelProperty("活码id") + private Long id; + + @ApiModelProperty("活动场景") + private String scenario; +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeDateVO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeDateVO.java new file mode 100644 index 0000000000000000000000000000000000000000..f3aea1a28452f04191f39011677ad84718f7631e --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeDateVO.java @@ -0,0 +1,47 @@ +package com.easyink.wecom.domain.vo.statistics.emplecode; + +import com.easyink.common.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 活码统计-日期维度VO + * + * @author lichaoyu + * @date 2023/7/5 20:56 + */ +@Data +@NoArgsConstructor +public class EmpleCodeDateVO extends EmpleCodeBaseVO{ + + @ApiModelProperty("日期") + @Excel(name = "日期", sort = 1) + private String time; + + public EmpleCodeDateVO(String time) { + this.time = time; + super.setAccumulateCustomerCnt(0); + super.setRetainCustomerCnt(0); + super.setNewCustomerCnt(0); + super.setLossCustomerCnt(0); + super.setCurrentNewCustomerCnt(0); + } + + /** + * 处理数据 + * + * @param accumulateCustomerCnt 累计客户数 + * @param retainCustomerCnt 留存客户总数 + * @param newCustomerCnt 新增客户数 + * @param lossCustomerCnt 流失客户数 + * @param currentNewCustomerCnt 截至当前时间,新增客户数 + */ + public void handleData(int accumulateCustomerCnt, int retainCustomerCnt, int newCustomerCnt, int lossCustomerCnt, int currentNewCustomerCnt) { + super.setAccumulateCustomerCnt(accumulateCustomerCnt); + super.setRetainCustomerCnt(retainCustomerCnt); + super.setNewCustomerCnt(newCustomerCnt); + super.setLossCustomerCnt(lossCustomerCnt); + super.setCurrentNewCustomerCnt(currentNewCustomerCnt); + } +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeUserVO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeUserVO.java new file mode 100644 index 0000000000000000000000000000000000000000..b12b1f41722e8180d4676d7564524a538b128f50 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeUserVO.java @@ -0,0 +1,95 @@ +package com.easyink.wecom.domain.vo.statistics.emplecode; + +import com.easyink.common.annotation.Excel; +import com.easyink.common.constant.GenConstants; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 活码统计-员工维度查询、导出接口响应实体 + * + * @author lichaoyu + * @date 2023/7/5 17:47 + */ +@Data +@NoArgsConstructor +public class EmpleCodeUserVO { + + @ApiModelProperty("员工Id") + private String userId; + @ApiModelProperty("员工姓名") + @Excel(name = "员工", sort = 1) + private String userName; + @ApiModelProperty("部门名称") + @Excel(name = "所属部门", sort = 2) + private String departmentName; + @ApiModelProperty("员工头像Url") + private String userHeadImage; + + @ApiModelProperty("累计添加客户") + @Excel(name = "累计添加客户", sort = 3) + private Integer accumulateCustomerCnt = 0; + + @ApiModelProperty("留存客户总数") + @Excel(name = "留存客户总数", sort = 4) + private Integer retainCustomerCnt = 0; + + @ApiModelProperty("新增客户数") + @Excel(name = "新增客户数", sort = 5) + private Integer newCustomerCnt = 0; + + @ApiModelProperty("流失客户数") + @Excel(name = "流失客户数", sort = 6) + private Integer lossCustomerCnt = 0; + + @ApiModelProperty("截止当前时间,新增客户数") + private Integer currentNewCustomerCnt = 0; + + @ApiModelProperty("新客留存率") + @Excel(name = "新客留存率", sort = 7) + private String retainNewCustomerRate; + + /** + * 留存率为空时返回的值 + */ + private final String NULL_VALUE = "-"; + + /** + * 新客留存率 公式:截止当前时间,新增客户数 / 新增客户数 + */ + public String getRetainNewCustomerRate() { + if (currentNewCustomerCnt == null || newCustomerCnt == null) { + return NULL_VALUE; + } + BigDecimal percent = new BigDecimal(100); + if(newCustomerCnt == 0) { + return NULL_VALUE; + } + // 百分比 + BigDecimal currCntDecimal = new BigDecimal(currentNewCustomerCnt); + BigDecimal newCntDecimal = new BigDecimal(newCustomerCnt); + int scale = 2; + // 计算留存率 截止当前时间,新增客户数 / 新客数 + return currCntDecimal + .multiply(percent) + .divide(newCntDecimal, scale, RoundingMode.HALF_UP) + .stripTrailingZeros().toPlainString(); + } + + /** + * 绑定导出数据 + * 导出框架不能直接使用get方法获取属性值 + */ + public void bindExportData() { + if (newCustomerCnt == 0) { + retainNewCustomerRate = NULL_VALUE; + } else { + retainNewCustomerRate = getRetainNewCustomerRate() + GenConstants.PERCENT; + } + } + +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeVO.java b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeVO.java new file mode 100644 index 0000000000000000000000000000000000000000..8fef816abaaca95990936a6e17813a6ed1505779 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/domain/vo/statistics/emplecode/EmpleCodeVO.java @@ -0,0 +1,24 @@ +package com.easyink.wecom.domain.vo.statistics.emplecode; + +import com.easyink.common.annotation.Excel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 活码统计-活码维度VO + * + * @author lichaoyu + * @date 2023/7/5 20:03 + */ +@Data +@NoArgsConstructor +public class EmpleCodeVO extends EmpleCodeBaseVO { + + @ApiModelProperty("活码名称") + @Excel(name = "活码", sort = 1) + private String empleName; + + @ApiModelProperty("活码id") + private String empleCodeId; +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/factory/impl/customer/WeCallBackAddExternalContactImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/factory/impl/customer/WeCallBackAddExternalContactImpl.java index a3a45ee247eee8859d07cc4cdf98e6edecfabf49..800b1f1065b42f3add29ba482d78a73313cda425 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/factory/impl/customer/WeCallBackAddExternalContactImpl.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/factory/impl/customer/WeCallBackAddExternalContactImpl.java @@ -1,7 +1,6 @@ package com.easyink.wecom.factory.impl.customer; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.thread.ThreadUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; @@ -17,14 +16,12 @@ import com.easyink.common.enums.*; import com.easyink.common.enums.code.WelcomeMsgTypeEnum; import com.easyink.common.exception.CustomException; import com.easyink.common.lock.LockUtil; +import com.easyink.common.utils.DateUtils; +import com.easyink.wecom.domain.*; +import com.easyink.wecom.mapper.statistic.WeEmpleCodeStatisticMapper; import com.easyink.wecom.utils.redis.CustomerRedisCache; import com.easyink.common.utils.TagRecordUtil; -import com.easyink.wecom.domain.WeCustomer; -import com.easyink.wecom.domain.WeEmpleCode; -import com.easyink.wecom.domain.WeEmpleCodeTag; -import com.easyink.wecom.domain.WeFlowerCustomerRel; import com.easyink.wecom.domain.dto.AddWeMaterialDTO; -import com.easyink.wecom.domain.dto.WeMediaDTO; import com.easyink.wecom.domain.dto.WeWelcomeMsg; import com.easyink.wecom.domain.dto.common.*; import com.easyink.wecom.domain.dto.redeemcode.WeRedeemCodeDTO; @@ -46,10 +43,7 @@ import org.redisson.api.RLock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -103,9 +97,13 @@ public class WeCallBackAddExternalContactImpl extends WeEventStrategy { @Autowired private CustomerRedisCache customerRedisCache; + + private final WeEmpleCodeStatisticMapper weEmpleCodeStatisticMapper; + @Autowired - public WeCallBackAddExternalContactImpl(WeUserService weUserService) { + public WeCallBackAddExternalContactImpl(WeUserService weUserService, WeEmpleCodeStatisticMapper weEmpleCodeStatisticMapper) { this.weUserService = weUserService; + this.weEmpleCodeStatisticMapper = weEmpleCodeStatisticMapper; } @@ -238,7 +236,8 @@ public class WeCallBackAddExternalContactImpl extends WeEventStrategy { String empleCodeId = messageMap.getEmpleCodeId(); //更新活码数据统计 weEmpleCodeAnalyseService.saveWeEmpleCodeAnalyse(corpId, userId, externalUserId, empleCodeId, true); - + // 活码统计数据记录 + empleStatisticCount(corpId, userId, state); //查询外部联系人与通讯录关系数据 WeFlowerCustomerRel weFlowerCustomerRel = weFlowerCustomerRelService .getOne(new LambdaQueryWrapper() @@ -276,6 +275,38 @@ public class WeCallBackAddExternalContactImpl extends WeEventStrategy { } } + /** + * 活码统计数据记录 + * + * @param corpId 企业ID + * @param userId 员工ID + * @param empleCodeId 活码ID + */ + private void empleStatisticCount(String corpId, String userId, String empleCodeId) { + String date = DateUtils.dateTime(new Date()); + // 获取当前日期下活码-员工对应的统计数据 + WeEmpleCodeStatistic historyData = weEmpleCodeStatisticMapper.selectOne(new LambdaQueryWrapper() + .eq(WeEmpleCodeStatistic::getCorpId, corpId) + .eq(WeEmpleCodeStatistic::getUserId, userId) + .eq(WeEmpleCodeStatistic::getEmpleCodeId, empleCodeId) + .eq(WeEmpleCodeStatistic::getTime, date) + ); + // 没有历史数据,创建一条新数据 + if (historyData == null) { + WeEmpleCodeStatistic newData = new WeEmpleCodeStatistic(corpId, Long.valueOf(empleCodeId), userId, date); + newData.addHandle(); + // 保存新数据 + weEmpleCodeStatisticMapper.insert(newData); + } else { + // 存在数据,则将新增客户数+1 + List dataList = new ArrayList<>(); + historyData.setNewCustomerCnt(historyData.getNewCustomerCnt() + 1); + dataList.add(historyData); + // 更新数据 + weEmpleCodeStatisticMapper.batchInsertOrUpdate(dataList); + } + } + /** * 处理兑换码欢迎语 * diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/interceptor/WeUnionIdInterceptor.java b/easyink-wecom/src/main/java/com/easyink/wecom/interceptor/WeUnionIdInterceptor.java index 4528602600695225031bfec85bd0172199eed774..7e26e9baa949a335e6869d6aecc4a8388a2850a7 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/interceptor/WeUnionIdInterceptor.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/interceptor/WeUnionIdInterceptor.java @@ -63,7 +63,7 @@ public class WeUnionIdInterceptor implements Interceptor { @Override public void onSuccess(Object data, ForestRequest request, ForestResponse response) { - log.error("请求成功url:【{}】,result:【{}】", request.getUrl(), response.getContent()); + log.info("请求成功url:【{}】,result:【{}】", request.getUrl(), response.getContent()); } @Override diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeAnalyseMapper.java b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeAnalyseMapper.java index 57a1f6e536f2e4e0558f01a68eb1bf0d8f59ec7f..49e2ceafd5d259a17cde5c0b4cb080b2387920d0 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeAnalyseMapper.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeAnalyseMapper.java @@ -2,8 +2,10 @@ package com.easyink.wecom.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.easyink.wecom.domain.WeEmpleCodeAnalyse; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeAnalyseDTO; import com.easyink.wecom.domain.vo.WeEmplyCodeAnalyseCountVO; +import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -16,6 +18,14 @@ import java.util.List; */ @Repository public interface WeEmpleCodeAnalyseMapper extends BaseMapper { + /** + * 根据活码Id获取员工Id列表 + * + * @param corpId 企业ID + * @param empleCodeId 活码ID + * @return userId列表 + */ + List selectUserIdsById(@Param("corpId") String corpId, @Param("empleCodeId") Long empleCodeId); /** * 查询 @@ -40,4 +50,33 @@ public interface WeEmpleCodeAnalyseMapper extends BaseMapper * @return int */ int insert(WeEmpleCodeAnalyse weEmpleCodeAnalyse); + + /** + * 获取企业下所有活码-员工对应的累计客户数 + * + * @param corpId 企业ID + * @param date 日期 格式为:YYYY-MM-DD + * @param empleCodeIdList 活码ID列表 + * @return 统计数据 + */ + List getAccumulateData(@Param("corpId") String corpId, @Param("date") String date, @Param("empleCodeIdList") List empleCodeIdList); + + /** + * 获取企业下所有活码-员工对应的留存客户数总数 + * + * @param corpId 企业ID + * @param date 日期 格式为:YYYY-MM-DD + * @param empleCodeIdList 活码ID列表 + * @return 统计数据 + */ + List getRetainData(@Param("corpId") String corpId, @Param("date") String date, @Param("empleCodeIdList") List empleCodeIdList); + + /** + * 获取企业下所有活码-员工对应的新增客户数和流失客户数 + * + * @param corpId 企业ID + * @param date 日期 格式为:YYYY-MM-DD + * @return 统计数据 + */ + List getEmpleStatisticDateData(@Param("corpId") String corpId, @Param("date") String date, @Param("empleCodeIdList") List empleCodeIdList); } diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeMapper.java b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeMapper.java index e66c27c016bfce6364503432b49bb53e5f39730b..de19775bb9a085bece8eefec1f8cfb80884a4d1b 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeMapper.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/WeEmpleCodeMapper.java @@ -3,9 +3,9 @@ package com.easyink.wecom.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.easyink.wecom.domain.WeEmpleCode; import com.easyink.wecom.domain.dto.WeEmpleCodeDTO; -import com.easyink.wecom.domain.dto.WeExternalContactDTO; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeDTO; import com.easyink.wecom.domain.vo.*; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeByNameVO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @@ -131,4 +131,12 @@ public interface WeEmpleCodeMapper extends BaseMapper { * @return */ List getUserFromDepartmentByEmplyCodeId(String corpId, Long id); + + /** + * 活码统计-根据活动场景模糊查询活码信息 + * + * @param dto {@link FindWeEmpleCodeDTO} + * @return {@link EmpleCodeByNameVO} + */ + List listByName(FindWeEmpleCodeDTO dto); } diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/mapper/statistic/WeEmpleCodeStatisticMapper.java b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/statistic/WeEmpleCodeStatisticMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..f22d3f2f9f0683261fbc8168cf93db81cd1a202b --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/mapper/statistic/WeEmpleCodeStatisticMapper.java @@ -0,0 +1,108 @@ +package com.easyink.wecom.mapper.statistic; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; +import com.easyink.wecom.domain.dto.statistics.EmpleCodeStatisticDTO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeBaseVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeDateVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeUserVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + + +/** + * 活码统计Mapper接口 + * + * @author lichaoyu + * @date 2023/7/5 14:35 + */ +@Repository +@Mapper +public interface WeEmpleCodeStatisticMapper extends BaseMapper { + + /** + * 活码统计-数据总览 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeBaseVO} + */ + EmpleCodeBaseVO listEmpleTotal(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-员工维度-获取基础数据 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + List listEmpleUser(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-员工维度-获取截止当前时间下,员工新增客户数 + * + * @param corpId 企业ID + * @param empleCodeIdList 活码ID列表 + * @param userIds 员工ID列表 + * @param time 时间 格式为 YYYY-MM-DD HH:MM:SS + * @return {@link EmpleCodeUserVO} + */ + List listUserCustomerRel(@Param("corpId") String corpId, @Param("empleCodeIdList") List empleCodeIdList, @Param("userIds") List userIds, @Param("time") String time, @Param("beginTime") String beginTime); + + /** + * 活码统计-活码维度-获取基础数据 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + List listEmple(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-活码维度-获取截止当前时间下,员工新增客户数 + * + * @param corpId 企业ID + * @param empleCodeIdList 活码ID列表 + * @param userIds 员工ID列表 + * @param time 时间 格式为 YYYY-MM-DD HH:MM:SS + * @return {@link EmpleCodeUserVO} + */ + List listStateUserCustomerRel(@Param("corpId") String corpId, @Param("empleCodeIdList") List empleCodeIdList, @Param("userIds") List userIds, @Param("time") String time, @Param("beginTime") String beginTime); + + /** + * 活码统计-日期维度-获取基础数据 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeDateVO} + */ + List listEmpleDate(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-日期维度-获取每个日期下的留存客户数和累计客户数 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeDateVO} + */ + List listDateAccumulateRetainCnt(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-日期维度-获取截止当前时间下,员工新增客户数 + * + * @param corpId 企业ID + * @param empleCodeIdList 活码ID列表 + * @param userIds 员工ID列表 + * @param time 时间 格式为 YYYY-MM-DD HH:MM:SS + * @return {@link EmpleCodeUserVO} + */ + List listEmpleDateUserCustomerRel(@Param("corpId") String corpId, @Param("empleCodeIdList") List empleCodeIdList, @Param("userIds") List userIds, @Param("time") String time); + + /** + * 批量插入或更新统计数据 + * + * @param list 统计数据 + * @return 结果 + */ + Integer batchInsertOrUpdate(@Param("list") List list); +} + diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeAnalyseService.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeAnalyseService.java index 3bb8ea61187f8868884fa5bdbdd0bf2c36d2e8df..9c55baeb12c358f50a9ea24da3e05e1a673aa270 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeAnalyseService.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeAnalyseService.java @@ -3,9 +3,12 @@ package com.easyink.wecom.service; import com.baomidou.mybatisplus.extension.service.IService; import com.easyink.common.core.domain.AjaxResult; import com.easyink.wecom.domain.WeEmpleCodeAnalyse; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeAnalyseDTO; import com.easyink.wecom.domain.vo.WeEmplyCodeAnalyseVO; +import java.util.List; + /** * 类名:WeEmpleCodeAnalyseService * @@ -49,4 +52,13 @@ public interface WeEmpleCodeAnalyseService extends IService * @return int */ int getAddCountByState(String state); + + /** + * 获取企业下所有活码-员工对应的统计数据 + * + * @param corpId 企业ID + * @param date 日期 格式为YYYY-MM-DD + * @return 统计数据 + */ + List getEmpleStatisticData(String corpId, String date); } diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeService.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeService.java index da56857a9003727de2000ac3435d8288611c9a85..8b21bd72ec4b59320939dc7b0b9eceb3673fb5a1 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeService.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/WeEmpleCodeService.java @@ -7,6 +7,7 @@ import com.easyink.wecom.domain.dto.WeExternalContactDTO; import com.easyink.wecom.domain.dto.emplecode.AddWeEmpleCodeDTO; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeDTO; import com.easyink.wecom.domain.vo.*; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeByNameVO; import java.util.List; @@ -147,4 +148,12 @@ public interface WeEmpleCodeService extends IService { * @return short mini app link */ String getCodeAppLink(Long id); + + /** + * 活码统计-根据活动场景模糊查询活码信息 + * + * @param dto {@link FindWeEmpleCodeDTO} + * @return {@link EmpleCodeByNameVO} + */ + List listByName(FindWeEmpleCodeDTO dto); } diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeAutoConfigServiceImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeAutoConfigServiceImpl.java index 5551db260919f721a8208741dd0f482f9b6e6dfd..fff344de79d66ed485ed6a717963fdfee7fdd4a5 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeAutoConfigServiceImpl.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeAutoConfigServiceImpl.java @@ -830,7 +830,8 @@ public class WeAutoConfigServiceImpl implements WeAutoConfigService { } else { log.info("已配置过侧边栏画像"); } - + // 自动化配置时取消侧边栏应用工具配置 Tower 任务: 应用管理屏蔽青鸾工单系统 ( https://tower.im/teams/636204/todos/70495 ) + needApplication = false; if (needApplication) { ThreadUtil.sleep(300); log.info("配置侧边栏应用工具"); diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeAnalyseServiceImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeAnalyseServiceImpl.java index bb51e220de50da6d2ef792b473092fc2de9f1b5c..dd88753adf8f6b0d9445f8aefd5b4b80020af80e 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeAnalyseServiceImpl.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeAnalyseServiceImpl.java @@ -3,8 +3,8 @@ package com.easyink.wecom.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.easyink.common.core.domain.AjaxResult; -import com.easyink.common.core.domain.entity.SysDictData; import com.easyink.common.core.domain.wecom.WeDepartment; +import com.easyink.common.core.domain.wecom.WeUser; import com.easyink.common.enums.ResultTip; import com.easyink.common.enums.WeEmpleCodeAnalyseTypeEnum; import com.easyink.common.exception.CustomException; @@ -12,13 +12,12 @@ import com.easyink.common.utils.DateUtils; import com.easyink.common.utils.poi.ExcelUtil; import com.easyink.wecom.domain.WeEmpleCode; import com.easyink.wecom.domain.WeEmpleCodeAnalyse; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; +import com.easyink.wecom.domain.WeEmpleCodeUseScop; import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeAnalyseDTO; import com.easyink.wecom.domain.vo.WeEmplyCodeAnalyseCountVO; import com.easyink.wecom.domain.vo.WeEmplyCodeAnalyseVO; -import com.easyink.wecom.mapper.WeDepartmentMapper; -import com.easyink.wecom.mapper.WeEmpleCodeAnalyseMapper; -import com.easyink.wecom.mapper.WeEmpleCodeMapper; -import com.easyink.wecom.mapper.WeUserMapper; +import com.easyink.wecom.mapper.*; import com.easyink.wecom.service.WeEmpleCodeAnalyseService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -47,6 +46,10 @@ public class WeEmpleCodeAnalyseServiceImpl extends ServiceImpl getEmpleStatisticData(String corpId, String date) { + if (StringUtils.isBlank(corpId) || StringUtils.isBlank(date)) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + // 获取需要统计数据的活码(未被删除的活码) + List weEmpleCodes = weEmpleCodeMapper.selectList(new LambdaQueryWrapper() + .eq(WeEmpleCode::getCorpId, corpId) + .eq(WeEmpleCode::getDelFlag, false)); + if (CollectionUtils.isEmpty(weEmpleCodes)) { + return new ArrayList<>(); + } + // 获取活码ID列表 + List empleCodeIdList = weEmpleCodes.stream().map(WeEmpleCode::getId).collect(Collectors.toList()); + // 初始化统计表数据 + List resultList = initData(corpId, empleCodeIdList, date); + // 获取企业下所有活码-员工对应的新增客户数和流失客户数 + List newAndLossCntList = baseMapper.getEmpleStatisticDateData(corpId, date, empleCodeIdList); + // 获取企业下所有活码-员工对应的累计客户数 + List accumulateList = baseMapper.getAccumulateData(corpId, date, empleCodeIdList); + // 获取企业下所有活码-员工对应的留存客户数总数 + List retainCntList = baseMapper.getRetainData(corpId, date, empleCodeIdList); + // 处理数据 + resultList.forEach(result -> { + // 将新增客户数和流失客户数设置到对应的活码中,为活码id相同且userid相同的员工设置新增客户数和流失客户数 + newAndLossCntList.stream().filter(newAndLossItem -> result.getEmpleCodeId().equals(newAndLossItem.getEmpleCodeId()) && result.getUserId().equals(newAndLossItem.getUserId())) + .findFirst() + .ifPresent(empleCodeStatistic -> { + result.setNewCustomerCnt(empleCodeStatistic.getNewCustomerCnt()); + result.setLossCustomerCnt(empleCodeStatistic.getLossCustomerCnt()); + }); + // 将累计客户数设置到对应的活码中,为活码id相同且userid相同的员工设置累计客户数 + accumulateList.stream().filter(accumulateItem -> result.getEmpleCodeId().equals(accumulateItem.getEmpleCodeId()) && result.getUserId().equals(accumulateItem.getUserId())) + .findFirst() + .ifPresent(empleCodeStatistic -> result.setAccumulateCustomerCnt(empleCodeStatistic.getAccumulateCustomerCnt())); + // 将留存客户总数设置到对应的活码中,为活码id相同且userid相同的员工设置留存客户总数 + retainCntList.stream().filter(retainItem -> result.getEmpleCodeId().equals(retainItem.getEmpleCodeId()) && result.getUserId().equals(retainItem.getUserId())) + .findFirst() + .ifPresent(empleCodeStatistic -> result.setRetainCustomerCnt(empleCodeStatistic.getRetainCustomerCnt())); + }); + return resultList; + } + + /** + * 初始化数据 + * + * @param corpId 企业ID + * @param empleCodeIdList 活码ID列表 + * @param date 日期,格式为 YYYY-MM-DD + * @return 初始化数据 + */ + private List initData(String corpId, List empleCodeIdList, String date) { + List resultList = new ArrayList<>(); + // 查询使用人 + List useScopeList = weEmpleCodeUseScopMapper.selectWeEmpleCodeUseScopListByIds(empleCodeIdList, corpId); + // 查询使用部门(查询使用人时需要用businessId关联we_user表,活码使用部门时不传入businessId) + List departmentScopeList = weEmpleCodeUseScopMapper.selectDepartmentWeEmpleCodeUseScopListByIds(empleCodeIdList); + for (Long empleCodeId : empleCodeIdList) { + // 使用人,部门不存在则跳过当前活码 + if (CollectionUtils.isEmpty(useScopeList) && CollectionUtils.isEmpty(departmentScopeList)) { + continue; + } + // 获取当前活码对应的userId + List userIds = getUserIds(useScopeList.stream().filter(item -> item.getEmpleCodeId().equals(empleCodeId)).collect(Collectors.toList()), + departmentScopeList.stream().filter(item -> item.getEmpleCodeId().equals(empleCodeId)).collect(Collectors.toList()), corpId, empleCodeId); + // 获取不到userId则跳过当前活码 + if (CollectionUtils.isEmpty(userIds)) { + continue; + } + // 根据userId,初始化统计数据 + for (String userId : userIds) { + WeEmpleCodeStatistic data = new WeEmpleCodeStatistic(corpId, empleCodeId, userId, date); + resultList.add(data); + } + } + return resultList; + } + + /** + * 根据使用人和部门范围获取UserId + * + * @param useScopeList 使用人范围列表 + * @param departmentScopeList 部门范围列表 + * @param corpId 企业ID + * @param empleCodeId 活码ID + * @return userId 列表 + */ + private List getUserIds(List useScopeList, List departmentScopeList, String corpId, Long empleCodeId) { + // 去重处理 + HashSet userIds = new HashSet<>(); + // 从使用人获取userId + if (CollectionUtils.isNotEmpty(useScopeList)) { + // 添加userId + userIds.addAll(useScopeList.stream().map(WeEmpleCodeUseScop::getBusinessId).collect(Collectors.toList())); + } + // 从部门获取userId + if (CollectionUtils.isNotEmpty(departmentScopeList)) { + // 获取部门id + List departmentIds = departmentScopeList.stream().map(WeEmpleCodeUseScop::getBusinessId).collect(Collectors.toList()); + // 根据部门获取员工信息 + List weUserList = weUserMapper.getUserByDepartmentList(corpId, departmentIds.toArray(new String[0])); + // 部门下没有userId,则直接返回上一步获取的userId列表 + if (CollectionUtils.isEmpty(weUserList)) { + return new ArrayList<>(userIds); + } + // 添加userId + userIds.addAll(weUserList.stream().map(WeUser::getUserId).collect(Collectors.toList())); + } + // 从活码分析表获取活码员工ID + List analysesUserIds = weEmpleCodeAnalyseMapper.selectUserIdsById(corpId, empleCodeId); + // 添加userId + if (CollectionUtils.isNotEmpty(analysesUserIds)) { + userIds.addAll(analysesUserIds); + } + return new ArrayList<>(userIds); + } /** * 保存员工活码数据统计 diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeServiceImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeServiceImpl.java index be39f952263486adf7af643ffb77e0f36768d0e1..44be9df61b9c026d5eccabdf0c2edb6fe12970e7 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeServiceImpl.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeEmpleCodeServiceImpl.java @@ -27,6 +27,7 @@ import com.easyink.wecom.domain.dto.emplecode.FindWeEmpleCodeDTO; import com.easyink.wecom.domain.entity.redeemcode.WeRedeemCode; import com.easyink.wecom.domain.vo.*; import com.easyink.wecom.domain.vo.redeemcode.WeRedeemCodeActivityVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeByNameVO; import com.easyink.wecom.handler.shorturl.EmpleCodeShortUrlHandler; import com.easyink.wecom.login.util.LoginTokenService; import com.easyink.wecom.mapper.WeEmpleCodeMapper; @@ -751,6 +752,21 @@ public class WeEmpleCodeServiceImpl extends ServiceImpl listByName(FindWeEmpleCodeDTO dto) { + if (StringUtils.isBlank(dto.getCorpId())) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + return this.baseMapper.listByName(dto); + + } + /** * 设置活码使用者名称和电话 * diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeUserCustomerMessageStatisticsServiceImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeUserCustomerMessageStatisticsServiceImpl.java index eaa1e0dbce62845df278725b90f05ebab8cb3625..677746b7c6a1907fe7d7b928960e60ec586601de 100644 --- a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeUserCustomerMessageStatisticsServiceImpl.java +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/WeUserCustomerMessageStatisticsServiceImpl.java @@ -16,6 +16,7 @@ import com.easyink.common.enums.StaffActivateEnum; import com.easyink.common.utils.DateUtils; import com.easyink.common.utils.bean.BeanUtils; import com.easyink.common.utils.poi.ExcelUtil; +import com.easyink.common.utils.sql.BatchInsertUtil; import com.easyink.wecom.domain.WeUserBehaviorData; import com.easyink.wecom.domain.dto.statistics.*; import com.easyink.wecom.domain.entity.WeUserCustomerMessageStatistics; @@ -135,7 +136,7 @@ public class WeUserCustomerMessageStatisticsServiceImpl extends ServiceImpl { + visibleUser.forEach(weUser -> { try { //根据员工id在会话存档中获取全部对话 ConversationArchiveQuery archiveQuery = new ConversationArchiveQuery(); @@ -220,6 +221,10 @@ public class WeUserCustomerMessageStatisticsServiceImpl extends ServiceImpl() + .eq(WeUserCustomerMessageStatistics::getCorpId, weUser.getCorpId()) + .eq(WeUserCustomerMessageStatistics::getUserId, weUser.getUserId()) + .eq(WeUserCustomerMessageStatistics::getSendTime, time)); this.save(weUserCustomerMessageStatistics); return; } @@ -289,21 +294,26 @@ public class WeUserCustomerMessageStatisticsServiceImpl extends ServiceImpl() + .eq(WeUserCustomerMessageStatistics::getCorpId, weUser.getCorpId()) + .eq(WeUserCustomerMessageStatistics::getUserId, weUser.getUserId()) + .eq(WeUserCustomerMessageStatistics::getSendTime, time)); this.saveBatch(userCustomerMessageStatisticsList); // 保存用户行为 saveUserBehaviorDate(userBehaviorData, thirtyMinReplyCount, newCustomerStartContactCnt, chatCnt, userActiveChatCnt); diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/statistic/WeEmpleCodeStatisticImpl.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/statistic/WeEmpleCodeStatisticImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..6aef5607935c204679f9f40c2bac2cd455a4888c --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/impl/statistic/WeEmpleCodeStatisticImpl.java @@ -0,0 +1,336 @@ +package com.easyink.wecom.service.impl.statistic; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.easyink.common.core.domain.AjaxResult; +import com.easyink.common.core.domain.wecom.WeUser; +import com.easyink.common.enums.CustomerStatusEnum; +import com.easyink.common.enums.ResultTip; +import com.easyink.common.exception.CustomException; +import com.easyink.common.utils.DateUtils; +import com.easyink.common.utils.poi.ExcelUtil; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; +import com.easyink.wecom.domain.WeFlowerCustomerRel; +import com.easyink.wecom.domain.dto.statistics.EmpleCodeStatisticDTO; +import com.easyink.wecom.domain.vo.statistics.emplecode.*; +import com.easyink.wecom.mapper.WeUserMapper; +import com.easyink.wecom.mapper.statistic.WeEmpleCodeStatisticMapper; +import com.easyink.wecom.service.WeFlowerCustomerRelService; +import com.easyink.wecom.service.statistic.WeEmpleCodeStatisticService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 活码统计Service业务处理层 + * + * @author lichaoyu + * @date 2023/7/5 14:34 + */ +@Slf4j +@Service +public class WeEmpleCodeStatisticImpl extends ServiceImpl implements WeEmpleCodeStatisticService { + + + private final WeUserMapper weUserMapper; + + private final WeFlowerCustomerRelService weFlowerCustomerRelService; + /** + * 活码维度报表名称 + */ + private final String EMPLE_NAME = "活码统计报表(活码维度)"; + /** + * 员工维度报表名称 + */ + private final String EMPLE_USER_NAME = "活码统计报表(员工维度)"; + /** + * 日期维度报表名称 + */ + private final String EMPLE_DATE_NAME = "活码统计报表(日期维度)"; + + public WeEmpleCodeStatisticImpl(WeUserMapper weUserMapper, WeFlowerCustomerRelService weFlowerCustomerRelService) { + this.weUserMapper = weUserMapper; + this.weFlowerCustomerRelService = weFlowerCustomerRelService; + } + + /** + * 活码统计-数据总览 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeBaseVO} + */ + @Override + public EmpleCodeBaseVO listEmpleTotal(EmpleCodeStatisticDTO dto) { + if (dto == null || StringUtils.isBlank(dto.getCorpId())) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + // 设置部门下的员工id列表 + setUserListByDepartment(dto); + // 获取基础数据 + EmpleCodeBaseVO empleCodeBaseVOS = this.baseMapper.listEmpleTotal(dto); + int currentCustomerCnt = 0; + // 不存在数据,返回默认值,而不是null + if (empleCodeBaseVOS == null) { + return new EmpleCodeBaseVO(); + } + // 存在数据,则查询活码对应的截止当前时间下,新增客户数 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // 统计we_flower_customer_rel表中state = 活码id,status != 1,2,时间为截止日期(YYYY-MM-DD HH:MM:DD) 的记录数 + queryWrapper.eq(WeFlowerCustomerRel::getCorpId, dto.getCorpId()) + .notIn(WeFlowerCustomerRel::getStatus, CustomerStatusEnum.DRAIN.getCode(), CustomerStatusEnum.DELETE.getCode()) + .gt(WeFlowerCustomerRel::getCreateTime, DateUtils.parseBeginDay(dto.getBeginDate())) + .lt(WeFlowerCustomerRel::getCreateTime, DateUtils.parseEndDay(dto.getEndDate())); + if (CollectionUtils.isNotEmpty(dto.getEmpleCodeIdList())) { + queryWrapper.in(WeFlowerCustomerRel::getState, dto.getEmpleCodeIdList()); + } + if (CollectionUtils.isNotEmpty(dto.getUserIds())) { + queryWrapper.in(WeFlowerCustomerRel::getUserId, dto.getUserIds()); + } + currentCustomerCnt = weFlowerCustomerRelService.count(queryWrapper); + // 设置截止当前时间下的新增客户数 + empleCodeBaseVOS.setCurrentNewCustomerCnt(currentCustomerCnt); + return empleCodeBaseVOS; + } + + /** + * 活码统计-员工维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + @Override + public List listEmpleUser(EmpleCodeStatisticDTO dto) { + if (dto == null || StringUtils.isBlank(dto.getCorpId())) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + // 活码id为空,无查询数据 + if (CollectionUtils.isEmpty(dto.getEmpleCodeIdList())) { + return new ArrayList<>(); + } + // 设置部门下的员工id列表 + setUserListByDepartment(dto); + // 获取统计数据 + List resultList = this.baseMapper.listEmpleUser(dto); + if (CollectionUtils.isEmpty(resultList)) { + return new ArrayList<>(); + } + // 获取截止当前时间,员工对应的新增客户数 + List userCustomerRels = this.baseMapper.listUserCustomerRel(dto.getCorpId(), dto.getEmpleCodeIdList(), dto.getUserIds(), DateUtils.parseEndDay(dto.getEndDate()), DateUtils.parseBeginDay(dto.getBeginDate())); + if (CollectionUtils.isNotEmpty(userCustomerRels)) { + // 为对应的员工设置截止当前时间,员工对应的新增客户数 + for (EmpleCodeUserVO empleCodeUserVO : resultList) { + for (EmpleCodeUserVO userCustomerRel : userCustomerRels) { + if (empleCodeUserVO.getUserId().equals(userCustomerRel.getUserId())) { + empleCodeUserVO.setCurrentNewCustomerCnt(userCustomerRel.getCurrentNewCustomerCnt()); + } + } + } + } + return resultList; + } + + /** + * 活码统计-员工维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + @Override + public AjaxResult exportEmpleUser(EmpleCodeStatisticDTO dto) { + List list = this.listEmpleUser(dto); + // 导出 + list.forEach(EmpleCodeUserVO::bindExportData); + ExcelUtil util = new ExcelUtil<>(EmpleCodeUserVO.class); + return util.exportExcel(list, EMPLE_USER_NAME); + } + + /** + * 活码统计-活码维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + @Override + public List listEmple(EmpleCodeStatisticDTO dto) { + if (dto == null || StringUtils.isBlank(dto.getCorpId())) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + if (CollectionUtils.isEmpty(dto.getEmpleCodeIdList())) { + return new ArrayList<>(); + } + // 设置部门下的员工id列表 + setUserListByDepartment(dto); + // 获取统计数据 + List resultList = this.baseMapper.listEmple(dto); + if (CollectionUtils.isEmpty(resultList)) { + return new ArrayList<>(); + } + // 获取截止查询时间,活码对应的新增客户数 + List empleUserCustomerRels = this.baseMapper.listStateUserCustomerRel(dto.getCorpId(), dto.getEmpleCodeIdList(), dto.getUserIds(), DateUtils.parseEndDay(dto.getEndDate()), DateUtils.parseBeginDay(dto.getBeginDate())); + if (CollectionUtils.isNotEmpty(empleUserCustomerRels)) { + // 根据活码id为对应的活码设置截止当前时间,员工对应的新增客户数 + for (EmpleCodeVO empleCodeVO : resultList) { + for (EmpleCodeVO empleRels : empleUserCustomerRels) { + if (empleCodeVO.getEmpleCodeId().equals(empleRels.getEmpleCodeId())) { + empleCodeVO.setCurrentNewCustomerCnt(empleRels.getCurrentNewCustomerCnt()); + } + } + } + } + return resultList; + } + + /** + * 活码统计-活码维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + @Override + public AjaxResult exportEmple(EmpleCodeStatisticDTO dto) { + List list = this.listEmple(dto); + // 导出 + list.forEach(EmpleCodeVO::bindExportData); + ExcelUtil util = new ExcelUtil<>(EmpleCodeVO.class); + return util.exportExcel(list, EMPLE_NAME); + } + + /** + * 活码统计-日期维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + @Override + public List listEmpleDate(EmpleCodeStatisticDTO dto) { + if (dto == null || StringUtils.isBlank(dto.getCorpId())) { + throw new CustomException(ResultTip.TIP_MISS_CORP_ID); + } + if (CollectionUtils.isEmpty(dto.getEmpleCodeIdList())) { + return new ArrayList<>(); + } + // 设置部门下的员工id列表 + setUserListByDepartment(dto); + // 获取统计数据 + List statisticList = this.baseMapper.listEmpleDate(dto); + List accumulateRetainCntList = this.baseMapper.listDateAccumulateRetainCnt(dto); + if (CollectionUtils.isEmpty(statisticList) || CollectionUtils.isEmpty(accumulateRetainCntList)) { + return getEmptyListByDate(dto); + } + // 组装累计客户数和留存客户总数 + for (EmpleCodeDateVO empleCodeDateVO : statisticList) { + for (EmpleCodeDateVO codeDateVO : accumulateRetainCntList) { + if (empleCodeDateVO.getTime().equals(codeDateVO.getTime())) { + empleCodeDateVO.setAccumulateCustomerCnt(codeDateVO.getAccumulateCustomerCnt()); + empleCodeDateVO.setRetainCustomerCnt(codeDateVO.getRetainCustomerCnt()); + } + } + } + // 获取截止当前时间,日期下,所有的活码对应的新增客户数 + List empleUserCustomerRels = this.baseMapper.listEmpleDateUserCustomerRel(dto.getCorpId(), dto.getEmpleCodeIdList(), dto.getUserIds(), DateUtils.parseEndDay(dto.getEndDate())); + // 为对应的日期设置截止当前时间,员工对应的新增客户数 + if (CollectionUtils.isNotEmpty(empleUserCustomerRels)) { + for (EmpleCodeDateVO empleCodeDateVO : statisticList) { + for (EmpleCodeDateVO empleDateRels : empleUserCustomerRels) { + if (empleCodeDateVO.getTime().equals(empleDateRels.getTime())) { + empleCodeDateVO.setCurrentNewCustomerCnt(empleDateRels.getCurrentNewCustomerCnt()); + } + } + } + } + // 组装结果数据 + List resultList = handleResultList(statisticList, dto); + return resultList; + } + + /** + * 组装结果数据 + * + * @param statisticList {@link EmpleCodeDateVO} + * @param dto {@link EmpleCodeStatisticDTO} + * @return 结果 + */ + private List handleResultList(List statisticList, EmpleCodeStatisticDTO dto) { + // 结果数据 + List resultList = getEmptyListByDate(dto); + // 组装数据 + for (EmpleCodeDateVO empleCodeDateVO : resultList) { + for (EmpleCodeDateVO codeDateVO : statisticList) { + if (empleCodeDateVO.getTime().equals(codeDateVO.getTime())) { + empleCodeDateVO.handleData( + codeDateVO.getAccumulateCustomerCnt(), + codeDateVO.getRetainCustomerCnt(), + codeDateVO.getNewCustomerCnt(), + codeDateVO.getLossCustomerCnt(), + codeDateVO.getCurrentNewCustomerCnt()); + } + } + } + return resultList; + } + + /** + * 根据日期获取默认空数据列表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 日期范围下的空数据列表 + */ + private List getEmptyListByDate(EmpleCodeStatisticDTO dto) { + List empleCodeDateVOList = new ArrayList<>(); + // 获取时间范围内的所有日期 + Date beginDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD, dto.getBeginDate()); + Date endDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD, dto.getEndDate()); + List dates = DateUtils.findDates(beginDate, endDate); + for (Date date : dates) { + EmpleCodeDateVO empleCodeDateVO = new EmpleCodeDateVO(DateUtils.dateTime(date)); + empleCodeDateVOList.add(empleCodeDateVO); + } + // 默认按照时间倒序排序 + empleCodeDateVOList.sort(Comparator.comparing(EmpleCodeDateVO::getTime).reversed()); + return empleCodeDateVOList; + } + + /** + * 活码统计-日期维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + @Override + public AjaxResult exportEmpleDate(EmpleCodeStatisticDTO dto) { + List list = this.listEmpleDate(dto); + // 导出 + list.forEach(EmpleCodeDateVO::bindExportData); + ExcelUtil util = new ExcelUtil<>(EmpleCodeDateVO.class); + return util.exportExcel(list, EMPLE_DATE_NAME); + } + + /** + * 当部门条件存在时,添加设置部门下的userId + * + * @param dto {@link EmpleCodeStatisticDTO} + */ + private void setUserListByDepartment(EmpleCodeStatisticDTO dto) { + if (dto == null || CollectionUtils.isEmpty(dto.getDepartmentIds())) { + return; + } + // 根据部门获取userid + List weUserList = weUserMapper.getUserByDepartmentList(dto.getCorpId(), dto.getDepartmentIds().toArray(new String[0])); + if (CollectionUtils.isEmpty(weUserList)) { + return; + } + // 添加到userid列表中 + if (CollectionUtils.isNotEmpty(dto.getUserIds())) { + dto.getUserIds().addAll(weUserList.stream().map(WeUser::getUserId).collect(Collectors.toList())); + } else { + dto.setUserIds(weUserList.stream().map(WeUser::getUserId).collect(Collectors.toList())); + } + } +} diff --git a/easyink-wecom/src/main/java/com/easyink/wecom/service/statistic/WeEmpleCodeStatisticService.java b/easyink-wecom/src/main/java/com/easyink/wecom/service/statistic/WeEmpleCodeStatisticService.java new file mode 100644 index 0000000000000000000000000000000000000000..f53925e0331af980357bd61afee590d51f1450f3 --- /dev/null +++ b/easyink-wecom/src/main/java/com/easyink/wecom/service/statistic/WeEmpleCodeStatisticService.java @@ -0,0 +1,78 @@ +package com.easyink.wecom.service.statistic; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.easyink.common.core.domain.AjaxResult; +import com.easyink.wecom.domain.WeEmpleCodeStatistic; +import com.easyink.wecom.domain.dto.statistics.EmpleCodeStatisticDTO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeBaseVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeDateVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeUserVO; +import com.easyink.wecom.domain.vo.statistics.emplecode.EmpleCodeVO; + +import java.util.List; + + +/** + * 活码统计功能(we_emple_code_statistic)表服务接口 + * + * @author lichaoyu + * @date 2023/7/5 13:43 + */ +public interface WeEmpleCodeStatisticService extends IService { + + /** + * 活码统计-数据总览 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeBaseVO} + */ + EmpleCodeBaseVO listEmpleTotal(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-员工维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + List listEmpleUser(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-员工维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + AjaxResult exportEmpleUser(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-活码维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + List listEmple(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-活码维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + AjaxResult exportEmple(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-日期维度 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return {@link EmpleCodeUserVO} + */ + List listEmpleDate(EmpleCodeStatisticDTO dto); + + /** + * 活码统计-日期维度-导出报表 + * + * @param dto {@link EmpleCodeStatisticDTO} + * @return 报表 + */ + AjaxResult exportEmpleDate(EmpleCodeStatisticDTO dto); +} diff --git a/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeAnalyseMapper.xml b/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeAnalyseMapper.xml index 01807fc995d3692ed3e2c9b8641651857bddc143..a9a3215156e71cbd63dbddaa9518c97abc07c09d 100644 --- a/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeAnalyseMapper.xml +++ b/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeAnalyseMapper.xml @@ -61,6 +61,64 @@ GROUP BY `time` + + + + + + + + diff --git a/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeMapper.xml b/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeMapper.xml index fde273fa3e4cad7a3d904457769332a111eeaa8a..9bc487b30ce770af9c79e37619b6062a9b106d56 100644 --- a/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeMapper.xml +++ b/easyink-wecom/src/main/resources/mapper/wecom/WeEmpleCodeMapper.xml @@ -461,6 +461,15 @@ #{id} + + \ No newline at end of file diff --git a/easyink-wecom/src/main/resources/mapper/wecom/statistic/WeEmpleCodeStatisticMapper.xml b/easyink-wecom/src/main/resources/mapper/wecom/statistic/WeEmpleCodeStatisticMapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..c948874c484b96b212fd65175f6a61eb8139d26a --- /dev/null +++ b/easyink-wecom/src/main/resources/mapper/wecom/statistic/WeEmpleCodeStatisticMapper.xml @@ -0,0 +1,253 @@ + + + + + + INSERT INTO we_emple_code_statistic (corp_id, emple_code_id, user_id, accumulate_customer_cnt, retain_customer_cnt, new_customer_cnt, loss_customer_cnt, `time`) + VALUES + + ( + #{item.corpId}, #{item.empleCodeId}, #{item.userId}, #{item.accumulateCustomerCnt}, + #{item.retainCustomerCnt}, #{item.newCustomerCnt}, #{item.lossCustomerCnt}, #{item.time} + ) + + ON DUPLICATE KEY UPDATE + accumulate_customer_cnt = VALUES(accumulate_customer_cnt), + retain_customer_cnt = VALUES(retain_customer_cnt), + new_customer_cnt = VALUES(new_customer_cnt), + loss_customer_cnt = VALUES(loss_customer_cnt) + + + + + + + + + + + + + + + + + + diff --git a/sql/init/easyink.sql b/sql/init/easyink.sql index 6494ea4710acd5ae7444881aecee90c2a4abb4d4..b532f0db651e60de2ab7ca5d707232f14557c98a 100644 --- a/sql/init/easyink.sql +++ b/sql/init/easyink.sql @@ -271,13 +271,13 @@ INSERT INTO `sys_job` VALUES (6, '定时消息群发', 'SYSTEM', 'ryTask.messageTask', '0 */2 * * * ?', '1', '1', '0', 'admin', '2021-02-10 10:07:22', 'admin', '2021-07-27 09:09:55', ''); INSERT INTO `sys_job` -VALUES (7, '联系客户统计数据拉取', 'SYSTEM', 'UserBehaviorDataTak.getUserBehaviorData()', '0 0 4 * * ?', '1', '1', '0', 'admin', +VALUES (7, '联系客户统计数据拉取', 'SYSTEM', 'UserBehaviorDataTak.getUserBehaviorData()', '0 30 5 * * ?', '1', '1', '0', 'admin', '2021-02-25 16:47:59', 'admin', '2021-02-25 23:45:03', ''); INSERT INTO `sys_job` -VALUES (8, '群聊数据统计数据拉取', 'SYSTEM', 'GroupChatStatisticTask.getGroupChatData()', '0 0 5 * * ? ', '1', '1', '0', 'admin', +VALUES (8, '群聊数据统计数据拉取', 'SYSTEM', 'GroupChatStatisticTask.getGroupChatData()', '0 0 6 * * ? ', '1', '1', '0', 'admin', '2021-02-25 16:49:44', '', '2021-02-25 23:45:05', ''); INSERT INTO `sys_job` -VALUES (9, '首页数据统计', 'SYSTEM', 'PageHomeDataTask.getPageHomeDataData()', '0 30 5 * * ? ', '1', '1', '0', 'admin', +VALUES (9, '首页数据统计', 'SYSTEM', 'PageHomeDataTask.getPageHomeDataData()', '0 30 6 * * ?', '1', '1', '0', 'admin', '2021-02-25 16:52:23', '', '2021-02-25 23:45:07', ''); INSERT INTO `sys_job` VALUES (10, '删除过期素材', 'SYSTEM', 'RemoveMaterialTask.removeExpireMaterial()', '0 0 4 * * ? ', '1', '1', '0', 'admin', @@ -316,13 +316,32 @@ INSERT INTO `sys_job` VALUES (20, '定期查询客户分配情况任务', 'SYSTEM', 'transferResultTask.execute', '0 */5 * * * ?', '2', '1', '0', 'admin', '2021-12-01 18:25:03', 'admin', '2021-12-01 18:25:51', ''); INSERT INTO `sys_job` -VALUES (21, '数据统计定时任务', 'SYSTEM', 'DataStatisticsTask.getDataStatistics()', '0 0 6 * * ?', '2', '1', '0', 'admin', +VALUES (21, '数据统计定时任务', 'SYSTEM', 'DataStatisticsTask.getDataStatistics()', '0 30 7 * * ?', '2', '1', '0', 'admin', '2023-02-13 16:34:13', '', NULL, ''); -- 2023--6-8 silver_chariot 增加定时任务 Tower 任务: 执行批量打标签导致系统无法使用 ( https://tower.im/teams/636204/todos/69816 ) INSERT INTO `sys_job` (`job_id`, `job_name`, `job_group`, `invoke_target`, `cron_expression`, `misfire_policy`, `concurrent`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES ('22', '同步回调变更客户定时任务', 'SYSTEM', 'syncCustomerChangeTask.execute()', '0/30 * * * * ? ', '2', '1', '0', 'admin', '2023-06-08 19:31:58', 'admin', '2023-06-08 19:32:36', ''); +-- 2023-07-07 lichaoyu 增加定时任务 Tower 任务: 活码统计-定时任务统计数据处理 ( https://tower.im/teams/636204/todos/71488 ) +INSERT INTO `sys_job`(`job_id`, `job_name`, `job_group`, `invoke_target`, `cron_expression`, `misfire_policy`, + `concurrent`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) +VALUES ('23', '每小时活码统计数据定时任务', 'SYSTEM', 'EmpleStatisticTask.getEmpleStatisticData()', '0 3 * * * ?', '2', + '1', '0', 'admin', '2023-07-07 15:22:28', 'admin', '2023-07-07 15:23:05', ''); +INSERT INTO `sys_job`(`job_id`, `job_name`, `job_group`, `invoke_target`, `cron_expression`, `misfire_policy`, + `concurrent`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) +VALUES ('24', '每日活码统计数据定时任务(传参日期格式:YYYY-MM-DD)', 'SYSTEM', 'EmpleStatisticTask.getEmpleStatisticDateData('''')', '0 0 3 * * ?', '2', '1', + '0', 'admin', '2023-07-07 19:50:41', '', '2023-07-07 19:50:46', ''); +-- 2023-07-11 lichaoyu 添加二次数据统计定时任务 Tower 任务: 每天定时2次统计数据 ( https://tower.im/teams/636204/todos/69513 ) +INSERT INTO `sys_job` +VALUES ('25', '联系客户统计数据拉取', 'SYSTEM', 'UserBehaviorDataTak.getUserBehaviorData()', '0 0 12 * * ?', '1', '1', '0', 'admin', + '2023-07-11 10:15:59', 'admin', '2023-07-11 10:16:37', ''); +INSERT INTO `sys_job` +VALUES ('26', '群聊数据统计数据拉取', 'SYSTEM', 'GroupChatStatisticTask.getGroupChatData()', '0 30 12 * * ? ', '1', '1', '0', 'admin', + '2023-07-11 10:16:44', '', '2023-07-11 10:16:16', ''); +INSERT INTO `sys_job` +VALUES ('27', '数据统计定时任务', 'SYSTEM', 'DataStatisticsTask.getDataStatistics()', '0 30 13 * * ?', '2', '1', '0', 'admin', + '2023-07-11 10:17:13', '', NULL, ''); -- ---------------------------- -- Table structure for sys_menu @@ -1014,6 +1033,10 @@ INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path` INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2324, '新增打标任务', 2285, 51, '', NULL, 1, 'F', '0', '0', 'wecom:batchtag:add', '#', 'admin', '2023-06-07 09:49:09', '', NULL, ''); INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2325, '删除打标任务', 2285, 52, '', NULL, 1, 'F', '0', '0', 'wecom:batchtag:del', '#', 'admin', '2023-06-07 09:49:32', '', NULL, ''); INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2326, '导出打标任务报表', 2285, 53, '', NULL, 1, 'F', '0', '0', 'wecom:batchtag:export', '#', 'admin', '2023-06-07 09:49:51', '', NULL, ''); +-- 2023-07-10 lcy 补交initSQL Tower 任务: 初始化环境活码统计功能异常 ( https://tower.im/teams/636204/todos/71799 ) +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2327, '引流分析', 2312, 2, 'drainageAnalysis', NULL, 1, 'M', '0', '0', '', 'drainageAnalysis', 'admin', '2023-07-04 13:54:14', 'admin', '2023-07-05 17:42:47', ''); +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2328, '活码统计', 2327, 1, 'codeStatistics', 'drainageAnalysis/codeStatistics/index', 1, 'C', '0', '0', NULL, '#', 'admin', '2023-07-04 13:58:05', '', NULL, ''); +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2329, '导出报表', 2328, 1, '', NULL, 1, 'F', '0', '0', 'stastistic:codeStatistics:export', '#', 'admin', '2023-07-10 15:24:12', 'admin', '2023-07-10 18:10:25', ''); -- ---------------------------- -- Table structure for sys_role -- ---------------------------- @@ -2528,7 +2551,7 @@ CREATE TABLE `we_application_center` COMMENT ='应用中心表'; - +-- 2023-07-11 补交init修改的SQL Tower 任务: 应用管理屏蔽青鸾工单系统 ( https://tower.im/teams/636204/todos/70495 ) INSERT INTO `we_application_center` VALUES (2, '青鸾智能工单系统', '企微群聊自动分析反馈内容形成工单,自动根据工单状态变更回复工单内容。', '', @@ -2536,7 +2559,7 @@ VALUES (2, '青鸾智能工单系统', '企微群聊自动分析反馈内容形 '群聊关联客户:企微群聊关联工单系统客户关系对应;\r\n自动获取工单信息:根据NLP自动获取信息,形成工单;\r\n自动回复工单信息:工单状态变更,自动群聊@工单反馈人员,自动告知状态;\r\n工单报表:自动发送当日工单报表;', '使用该应用需进行初始化操作,进行工单系统注册、客服人员账号注册、客户资料维护;若您有疑问请扫描以下二维码,添加客服,咨询初始化操作事宜', 'https://wecomsaas-1253559996.cos.ap-guangzhou.myqcloud.com/2021/12/16/壹鸽咨询服务.png', - 1, '2021-12-20 09:59:03', 1, 'workSheetAssistant', 'http://121.37.253.126:8088'); + 0, '2021-12-20 09:59:03', 1, 'workSheetAssistant', 'http://121.37.253.126:8088'); CREATE TABLE `order_user_to_order_account` @@ -2726,7 +2749,7 @@ CREATE TABLE `we_emple_code_analyse` `emple_code_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '员工活码主键ID', `user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '企业成员userId', `external_userid` varchar(32) NOT NULL DEFAULT '' COMMENT '客户ID', - `time` date NOT NULL COMMENT '添加时间', + `time` date NOT NULL COMMENT 'type为1时是添加时间,type为0时是流失时间', `type` tinyint(1) NOT NULL COMMENT '1:新增,0:流失', PRIMARY KEY (`id`), UNIQUE KEY `uniq_corpid_codeid_userid_extid_type_time` (`corp_id`,`emple_code_id`,`user_id`,`external_userid`,`type`,`time`) USING BTREE COMMENT '唯一索引' @@ -3699,4 +3722,21 @@ CREATE TABLE `we_batch_tag_task_rel` ( `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `tag_id` varchar(64) NOT NULL DEFAULT '' COMMENT '此次任务需要打上的标签id', PRIMARY KEY (`task_id`,`tag_id`) -) ENGINE=InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT='批量打标签任务-标签关联表'; \ No newline at end of file +) ENGINE=InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT='批量打标签任务-标签关联表'; + +-- 2023-07-07 新增活码统计表 Tower 任务: 活码统计-定时任务统计数据处理 ( https://tower.im/teams/636204/todos/71488 ) +CREATE TABLE `we_emple_code_statistic` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `corp_id` varchar(64) NOT NULL DEFAULT '' COMMENT '企业ID', + `emple_code_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '活码id', + `user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '员工ID', + `accumulate_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '累计客户数', + `retain_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '留存客户数', + `new_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '新增客户数', + `loss_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '流失客户数', + `time` date NOT NULL COMMENT '日期', + PRIMARY KEY (`id`), + UNIQUE KEY `uni_emple_user_time` (`emple_code_id`,`user_id`,`time`) USING BTREE, + KEY `idx_corp_user_id` (`corp_id`,`user_id`) USING BTREE, + KEY `idx_emple_user_id` (`emple_code_id`,`user_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='活码数据统计表'; \ No newline at end of file diff --git a/sql/update/update-V1.30.0.sql b/sql/update/update-V1.30.0.sql new file mode 100644 index 0000000000000000000000000000000000000000..f5d145837421d18499a12f8ca3f48a1b7252d59b --- /dev/null +++ b/sql/update/update-V1.30.0.sql @@ -0,0 +1,64 @@ +-- 2023-07-06 应用管理屏蔽青鸾智能工单系统,将启用状态设为关闭 Tower 任务: 应用管理屏蔽青鸾工单系统 ( https://tower.im/teams/636204/todos/70495 ) +UPDATE we_application_center SET `enable` = FALSE WHERE name = '青鸾智能工单系统'; +-- 2023-07-07 lichaoyu 增加定时任务 Tower 任务: 活码统计-定时任务统计数据处理 ( https://tower.im/teams/636204/todos/71488 ) +INSERT INTO `sys_job`(`job_id`, `job_name`, `job_group`, `invoke_target`, `cron_expression`, `misfire_policy`, + `concurrent`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) +VALUES ('23', '每小时活码统计数据定时任务', 'SYSTEM', 'EmpleStatisticTask.getEmpleStatisticData()', '0 3 * * * ?', '2', + '1', '0', 'admin', '2023-07-07 15:22:28', 'admin', '2023-07-07 15:23:05', ''); +INSERT INTO `sys_job`(`job_id`, `job_name`, `job_group`, `invoke_target`, `cron_expression`, `misfire_policy`, + `concurrent`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) +VALUES ('24', '每日活码统计数据定时任务(传参日期格式:YYYY-MM-DD)', 'SYSTEM', 'EmpleStatisticTask.getEmpleStatisticDateData('''')', '0 0 3 * * ?', '2', '1', + '0', 'admin', '2023-07-07 19:50:41', '', '2023-07-07 19:50:46', ''); +-- 2023-07-07 新增活码统计表 Tower 任务: 活码统计-定时任务统计数据处理 ( https://tower.im/teams/636204/todos/71488 ) +CREATE TABLE `we_emple_code_statistic` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `corp_id` varchar(64) NOT NULL DEFAULT '' COMMENT '企业ID', + `emple_code_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '活码id', + `user_id` varchar(32) NOT NULL DEFAULT '' COMMENT '员工ID', + `accumulate_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '累计客户数', + `retain_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '留存客户数', + `new_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '新增客户数', + `loss_customer_cnt` int(11) NOT NULL DEFAULT '0' COMMENT '流失客户数', + `time` date NOT NULL COMMENT '日期', + PRIMARY KEY (`id`), + UNIQUE KEY `uni_emple_user_time` (`emple_code_id`,`user_id`,`time`) USING BTREE, + KEY `idx_corp_user_id` (`corp_id`,`user_id`) USING BTREE, + KEY `idx_emple_user_id` (`emple_code_id`,`user_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='活码数据统计表'; +-- 2023-07-10 lcy 新增活码统计权限/菜单 Tower 任务: 角色管理 ( https://tower.im/teams/636204/todos/71553 ) +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2327, '引流分析', 2312, 2, 'drainageAnalysis', NULL, 1, 'M', '0', '0', '', 'drainageAnalysis', 'admin', '2023-07-04 13:54:14', 'admin', '2023-07-05 17:42:47', ''); +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2328, '活码统计', 2327, 1, 'codeStatistics', 'drainageAnalysis/codeStatistics/index', 1, 'C', '0', '0', NULL, '#', 'admin', '2023-07-04 13:58:05', '', NULL, ''); +INSERT INTO `sys_menu`(`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2329, '导出报表', 2328, 1, '', NULL, 1, 'F', '0', '0', 'stastistic:codeStatistics:export', '#', 'admin', '2023-07-10 15:24:12', 'admin', '2023-07-10 18:10:25', ''); +-- 2023-07-10 lcy 给所有管理员增加菜单和权限 Tower 任务: 角色管理 ( https://tower.im/teams/636204/todos/71553 ) +INSERT INTO sys_role_menu(role_id, menu_id) SELECT role_id, 2327 FROM sys_role WHERE role_type = 1; +INSERT INTO sys_role_menu(role_id, menu_id) SELECT role_id, 2328 FROM sys_role WHERE role_type = 1; +INSERT INTO sys_role_menu(role_id, menu_id) SELECT role_id, 2329 FROM sys_role WHERE role_type = 1; +-- 2023-07-10 lcy 给所有部门管理员增加菜单和权限 Tower 任务: 角色管理 ( https://tower.im/teams/636204/todos/71553 ) +INSERT INTO sys_role_menu (role_id, menu_id) SELECT role_id, 2327 FROM sys_role WHERE role_type = 2 AND role_key = 'depart'; +INSERT INTO sys_role_menu (role_id, menu_id) SELECT role_id, 2328 FROM sys_role WHERE role_type = 2 AND role_key = 'depart'; +INSERT INTO sys_role_menu (role_id, menu_id) SELECT role_id, 2329 FROM sys_role WHERE role_type = 2 AND role_key = 'depart'; +-- 2023-07-11 lcy 删除原有自定角色的活码统计数据菜单权限 Tower 任务: 自定义角色默认没有活码统计权限 ( https://tower.im/teams/636204/todos/71658 ) +DELETE FROM sys_role_menu WHERE menu_id IN (2327, 2328) AND role_id IN (SELECT role_id FROM sys_role WHERE role_type = 3 AND role_key = ''); +-- 2023-07-11 lcy 给自定义角色添加菜单权限 Tower 任务: 自定义角色默认没有活码统计权限 ( https://tower.im/teams/636204/todos/71658 ) +INSERT INTO sys_role_menu (role_id, menu_id) SELECT role_id, 2327 FROM sys_role WHERE role_type = 3 AND role_key = ''; +INSERT INTO sys_role_menu (role_id, menu_id) SELECT role_id, 2328 FROM sys_role WHERE role_type = 3 AND role_key = ''; +-- 2023-07-11 lichaoyu 添加二次数据统计定时任务 Tower 任务: 每天定时2次统计数据 ( https://tower.im/teams/636204/todos/69513 ) +INSERT INTO `sys_job` +VALUES ('25', '联系客户统计数据拉取', 'SYSTEM', 'UserBehaviorDataTak.getUserBehaviorData()', '0 0 12 * * ?', '1', '1', '0', 'admin', + '2023-07-11 10:15:59', 'admin', '2023-07-11 10:16:37', ''); +INSERT INTO `sys_job` +VALUES ('26', '群聊数据统计数据拉取', 'SYSTEM', 'GroupChatStatisticTask.getGroupChatData()', '0 30 12 * * ? ', '1', '1', '0', 'admin', + '2023-07-11 10:16:44', '', '2023-07-11 10:16:16', ''); +INSERT INTO `sys_job` +VALUES ('27', '数据统计定时任务', 'SYSTEM', 'DataStatisticsTask.getDataStatistics()', '0 30 13 * * ?', '2', '1', '0', 'admin', + '2023-07-11 10:17:13', '', NULL, ''); +-- 2023-07-11 lichaoyu 更新原来的定时任务执行时间 Tower 任务: 每天定时2次统计数据 ( https://tower.im/teams/636204/todos/69513 ) +UPDATE sys_job SET cron_expression = '0 30 5 * * ?' WHERE job_id = 7; +UPDATE sys_job SET cron_expression = '0 0 6 * * ? ' WHERE job_id = 8; +UPDATE sys_job SET cron_expression = '0 30 6 * * ?' WHERE job_id = 9; +UPDATE sys_job SET cron_expression = '0 30 7 * * ?' WHERE job_id = 21; +-- 2023-07-11 lcy 修改活码详情表注释 Tower 任务: 活码详情表注释错误 ( https://tower.im/teams/636204/todos/71214 ) +ALTER TABLE we_emple_code_analyse MODIFY COLUMN `time` date NOT NULL COMMENT 'type为1时是添加时间,type为0时是流失时间'; +-- 2023-07-12 lcy 修改user_id字段长度 Tower 任务: 活码统计新客留存率统计异常 ( https://tower.im/teams/636204/todos/71707 ) +ALTER TABLE `we_emple_code_statistic` MODIFY COLUMN `user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '员工ID';