| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- package com.punchsettle.server.service.manager.impl;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.time.LocalDate;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.Optional;
- import java.util.function.Function;
- import java.util.stream.Collectors;
- import com.punchsettle.server.atomic.entity.User;
- import com.punchsettle.server.atomic.service.IUserService;
- import com.punchsettle.server.common.utils.Assert;
- import com.punchsettle.server.constant.UserCategoryEnum;
- import com.punchsettle.server.service.manager.IUserManager;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.stereotype.Component;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.CollectionUtils;
- import com.punchsettle.server.atomic.IStatPiTaskService;
- import com.punchsettle.server.atomic.StatPiTask;
- import com.punchsettle.server.atomic.entity.PiTask;
- import com.punchsettle.server.atomic.entity.PiTaskHistory;
- import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
- import com.punchsettle.server.atomic.entity.StatNewUser;
- import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
- import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
- import com.punchsettle.server.atomic.entity.StatPiTaskYear;
- import com.punchsettle.server.atomic.entity.StatPoints;
- import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
- import com.punchsettle.server.atomic.service.IPiTaskService;
- import com.punchsettle.server.atomic.service.ISettleTaskRelaHistoryService;
- import com.punchsettle.server.atomic.service.IStatNewUserService;
- import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
- import com.punchsettle.server.atomic.service.IStatPointsService;
- import com.punchsettle.server.constant.CacheNameConstant;
- import com.punchsettle.server.constant.PunchInResultEnum;
- import com.punchsettle.server.constant.SettleResultEnum;
- import com.punchsettle.server.constant.StatPeriodEnum;
- import com.punchsettle.server.core.config.BizProperties;
- import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
- import com.punchsettle.server.pojo.settle.SettleTaskRelaHistoryQuery;
- import com.punchsettle.server.pojo.stat.StatNewUserQuery;
- import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
- import com.punchsettle.server.pojo.stat.StatPointsQuery;
- import com.punchsettle.server.pojo.ucharts.LineSeriesVO;
- import com.punchsettle.server.pojo.ucharts.LineVO;
- import com.punchsettle.server.service.manager.IStatManager;
- import com.punchsettle.server.utiis.DateUtils;
- import com.punchsettle.server.utiis.UserUtils;
- /**
- * @author myou
- * @version 1.0.0
- * @date 2025/5/3 9:32
- * @description 统计数据服务类
- */
- @Component
- public class StatManagerImpl implements IStatManager {
- /**
- * 数值100
- */
- private static final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100);
- @Autowired
- private IStatPointsService statPointsService;
- @Autowired
- private IStatNewUserService statNewUserService;
- @Autowired
- private IPiTaskHistoryService piTaskHistoryService;
- @Autowired
- private BizProperties bizProperties;
- @Autowired
- private IStatPiTaskWeekService statPiTaskWeekService;
- @Autowired
- private ISettleTaskRelaHistoryService settleTaskRelaHistoryService;
- @Autowired
- private IPiTaskService piTaskService;
- @Autowired
- private IUserManager userManager;
- @Autowired
- private IUserService userService;
- @Override
- @Cacheable(cacheNames = CacheNameConstant.STAT_POINTS_LINE, key = "T(com.punchsettle.server.utiis.UserUtils).getCurrentUserId()")
- public LineVO queryStatPointsLine() {
- Long currentUserId = UserUtils.getCurrentUserId();
- LocalDate endDate = LocalDate.now();
- LocalDate startDate = endDate.minusDays(bizProperties.getLineItemCount());
- // 获取折线图时间范围
- List<LocalDate> dateRange = DateUtils.getDateRange(startDate, endDate);
- String[] lineCategories = dateRange.stream().map(v -> DateUtils.MM_DD_FORMATTER.format(v)).toArray(String[]::new);
- StatPointsQuery statPointsQuery = new StatPointsQuery();
- statPointsQuery.setUserId(currentUserId);
- statPointsQuery.setStatStartTime(startDate.toString());
- statPointsQuery.setStatEndTime(endDate.toString());
- List<StatPoints> statPointsList = statPointsService.queryByCondition(statPointsQuery);
- Map<String, StatPoints> statPointsMap = statPointsList.stream().collect(Collectors.toMap(v -> v.getStatTime().substring(5), Function.identity(), (v1, v2) -> v1));
- List<Integer> settlePointsList = new ArrayList<>(lineCategories.length);
- List<Integer> consumePointsList = new ArrayList<>(lineCategories.length);
- List<Integer> totalPointsList = new ArrayList<>(lineCategories.length);
- for (String lineCategory : lineCategories) {
- StatPoints statPoints = statPointsMap.get(lineCategory);
- if (Objects.isNull(statPoints)) {
- settlePointsList.add(null);
- consumePointsList.add(null);
- totalPointsList.add(null);
- continue;
- }
- settlePointsList.add(statPoints.getSettlePoints());
- consumePointsList.add(statPoints.getConsumePoints());
- totalPointsList.add(statPoints.getTotalPoints());
- }
- LineSeriesVO settlePointsLineSeriesVO = new LineSeriesVO();
- settlePointsLineSeriesVO.setName("结算积分");
- settlePointsLineSeriesVO.setData(settlePointsList.toArray(Integer[]::new));
- LineSeriesVO consumePointsLineSeriesVO = new LineSeriesVO();
- consumePointsLineSeriesVO.setName("消耗积分");
- consumePointsLineSeriesVO.setData(consumePointsList.toArray(Integer[]::new));
- LineSeriesVO totalPointsLineSeriesVO = new LineSeriesVO();
- totalPointsLineSeriesVO.setName("总积分");
- totalPointsLineSeriesVO.setData(totalPointsList.toArray(Integer[]::new));
- LineVO lineVO = new LineVO();
- lineVO.setCategories(lineCategories);
- lineVO.setSeries(Arrays.asList(settlePointsLineSeriesVO, consumePointsLineSeriesVO, totalPointsLineSeriesVO));
- return lineVO;
- }
- @Override
- @Cacheable(cacheNames = CacheNameConstant.STAT_NEW_USER_LINE)
- public LineVO queryStatNewUserLine() {
- User user = userManager.getByIdWithCache(UserUtils.getCurrentUserId());
- if (UserCategoryEnum.NORMAL.equals(user.getUserCategory())) {
- return null;
- }
- LocalDate endDate = LocalDate.now();
- LocalDate startDate = endDate.minusDays(bizProperties.getLineItemCount());
- // 获取折线图时间范围
- List<LocalDate> dateRange = DateUtils.getDateRange(startDate, endDate);
- String[] lineCategories = dateRange.stream().map(v -> DateUtils.MM_DD_FORMATTER.format(v)).toArray(String[]::new);
- StatNewUserQuery statNewUserQuery = new StatNewUserQuery();
- statNewUserQuery.setStatStartTime(startDate.toString());
- statNewUserQuery.setStatEndTime(endDate.toString());
- List<StatNewUser> statNewUserList = statNewUserService.queryByCondition(statNewUserQuery);
- Map<String, Integer> statNewUserMap = statNewUserList.stream().collect(Collectors.toMap(v -> v.getStatTime().substring(5), StatNewUser::getNewUserCount, (v1, v2) -> v1));
- List<Integer> newUserCountList = new ArrayList<>(lineCategories.length);
- for (String lineCategory : lineCategories) {
- Integer newUserCount = Optional.ofNullable(statNewUserMap.get(lineCategory)).orElse(0);
- newUserCountList.add(newUserCount);
- }
- LineSeriesVO newUserLineSeriesVO = new LineSeriesVO();
- newUserLineSeriesVO.setName("新增用户数");
- newUserLineSeriesVO.setData(newUserCountList.toArray(Integer[]::new));
- LineVO lineVO = new LineVO();
- lineVO.setCategories(lineCategories);
- lineVO.setSeries(Arrays.asList(newUserLineSeriesVO));
- return lineVO;
- }
- @Override
- @Cacheable(cacheNames = CacheNameConstant.STAT_TASK_LINE, key = "T(com.punchsettle.server.utiis.UserUtils).getCurrentUserId()")
- public LineVO queryStatTaskLine() {
- Long currentUserId = UserUtils.getCurrentUserId();
- LocalDate endDate = LocalDate.now();
- LocalDate startDate = endDate.minusDays(bizProperties.getLineItemCount());
- // 获取折线图时间范围
- List<LocalDate> dateRange = DateUtils.getDateRange(startDate, endDate);
- String[] lineCategories = dateRange.stream().map(v -> DateUtils.MM_DD_FORMATTER.format(v)).toArray(String[]::new);
- PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
- piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
- piTaskHistoryQuery.setPunchInDateFrom(startDate.toString());
- piTaskHistoryQuery.setPunchInDateTo(endDate.toString());
- List<PiTaskHistory> piTaskHistoryList = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
- Map<String, List<PiTaskHistory>> piTaskHistoryMap = piTaskHistoryList.stream().collect(Collectors.groupingBy(v -> v.getPunchInDate().substring(5)));
- // 总任务数
- List<Integer> totalTaskCountList = new ArrayList<>(lineCategories.length);
- // 打卡任务数
- List<Integer> punchInTaskCountList = new ArrayList<>(lineCategories.length);
- // 完成打卡任务数
- List<Integer> doneTaskCountList = new ArrayList<>(lineCategories.length);
- for (String lineCategory : lineCategories) {
- List<PiTaskHistory> piTaskHistories = piTaskHistoryMap.get(lineCategory);
- if (CollectionUtils.isEmpty(piTaskHistories)) {
- totalTaskCountList.add(0);
- punchInTaskCountList.add(0);
- doneTaskCountList.add(0);
- continue;
- }
- // 总任数
- totalTaskCountList.add(piTaskHistories.size());
- // TODO 这里要单独弄一个统计表,不然无法计算
- punchInTaskCountList.add(piTaskHistories.size());
- // 任务完成数
- doneTaskCountList.add(piTaskHistories.stream().filter(piTaskHistory -> piTaskHistory.getPunchInResult().equals(PunchInResultEnum.DONE)).collect(Collectors.toList()).size());
- }
- LineSeriesVO totalTaskCountLineSeriesVO = new LineSeriesVO();
- totalTaskCountLineSeriesVO.setName("总任务数");
- totalTaskCountLineSeriesVO.setData(totalTaskCountList.toArray(Integer[]::new));
- LineSeriesVO punchInTaskCountLineSeriesVO = new LineSeriesVO();
- punchInTaskCountLineSeriesVO.setName("打卡数量");
- punchInTaskCountLineSeriesVO.setData(punchInTaskCountList.toArray(Integer[]::new));
- LineSeriesVO doneTaskCountLineSeriesVO = new LineSeriesVO();
- doneTaskCountLineSeriesVO.setName("完成数量");
- doneTaskCountLineSeriesVO.setData(doneTaskCountList.toArray(Integer[]::new));
- LineVO lineVO = new LineVO();
- lineVO.setCategories(lineCategories);
- lineVO.setSeries(Arrays.asList(totalTaskCountLineSeriesVO, punchInTaskCountLineSeriesVO, doneTaskCountLineSeriesVO));
- return lineVO;
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void statPiTaskData(IStatPiTaskService statPiTaskService, StatPeriodEnum statPeriod, List<Long> userIds, LocalDate statTime, LocalDate statFirstDay, LocalDate statLastDay) {
- // 查询任务数据
- List<PiTask> piTasks = piTaskService.getActiveTask(userIds);
- // 没有待统计任务跳过
- if (CollectionUtils.isEmpty(piTasks)) {
- return;
- }
- StatPiTaskQuery statPiTaskQuery = new StatPiTaskQuery();
- statPiTaskQuery.setStatTime(statTime.toString());
- statPiTaskQuery.setUserIds(userIds);
- List<StatPiTask> statPiTaskDatas = statPiTaskService.queryByCondition(statPiTaskQuery);
- // 任务唯一ID - 周统计数据
- Map<Long, StatPiTask> statPiTaskDataMap = statPiTaskDatas.stream().collect(Collectors.toMap(StatPiTask::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
- // 查询已结算数据
- SettleTaskRelaHistoryQuery settleTaskRelaHistoryQuery = new SettleTaskRelaHistoryQuery();
- settleTaskRelaHistoryQuery.setUserIds(userIds);
- settleTaskRelaHistoryQuery.setSettleDateFrom(statFirstDay.toString());
- settleTaskRelaHistoryQuery.setSettleDateTo(statLastDay.toString());
- settleTaskRelaHistoryQuery.setSettleResult(SettleResultEnum.SETTLE);
- List<SettleTaskRelaHistory> settleTaskRelaHistorieList = settleTaskRelaHistoryService.queryByCondition(settleTaskRelaHistoryQuery);
- // 任务唯一ID - 结算任务关联记录
- Map<Long, List<SettleTaskRelaHistory>> settleTaskRelaHistoryMap = settleTaskRelaHistorieList.stream().collect(Collectors.groupingBy(SettleTaskRelaHistory::getPiTaskUniqueId));
- // 新增
- List<StatPiTask> addStatPiTaskWeekList = new ArrayList<>();
- // 更新
- List<StatPiTask> updateStatPiTaskWeekList = new ArrayList<>();
- for (PiTask piTask : piTasks) {
- // 获取结算数据
- List<SettleTaskRelaHistory> settleTaskRelaHistories = settleTaskRelaHistoryMap.get(piTask.getUniqueId());
- // 统计数据
- StatPiTask newStatPiTask = statPiTaskData(statPeriod, settleTaskRelaHistories);
- // 获取统计数据
- StatPiTask oldStatPiTaskWeek = statPiTaskDataMap.get(piTask.getUniqueId());
- // 如果没有统计数据,则创建
- if (Objects.isNull(oldStatPiTaskWeek)) {
- newStatPiTask.setUserId(piTask.getCreatedBy());
- newStatPiTask.setTaskUniqueId(piTask.getUniqueId());
- newStatPiTask.setStatTime(statTime.toString());
- addStatPiTaskWeekList.add(newStatPiTask);
- } else {
- newStatPiTask.setId(oldStatPiTaskWeek.getId());
- updateStatPiTaskWeekList.add(newStatPiTask);
- }
- }
- if (!CollectionUtils.isEmpty(addStatPiTaskWeekList)) {
- statPiTaskWeekService.insertList(addStatPiTaskWeekList);
- }
- if (!CollectionUtils.isEmpty(updateStatPiTaskWeekList)) {
- statPiTaskWeekService.batchUpdate(updateStatPiTaskWeekList);
- }
- }
- /**
- * 重新统计打卡任务数据,如果不存在结算记录,则所有数据为0
- * @param statPeriod 统计周期
- * @param settleTaskRelaHistories 结算记录
- * @return
- */
- private StatPiTask statPiTaskData(StatPeriodEnum statPeriod, List<SettleTaskRelaHistory> settleTaskRelaHistories) {
- List<SettleTaskRelaHistory> list = CollectionUtils.isEmpty(settleTaskRelaHistories) ? List.of() : settleTaskRelaHistories.stream().filter(v -> SettleResultEnum.SETTLE.equals(v.getSettleResult())).toList();
- // 总需打卡数
- int punchInTotalCount = list.size();
- // 打卡数
- int punchInCount = (int) list.stream().filter(v -> Objects.nonNull(v.getPiTaskHistoryId())).count();
- // 打卡完成数
- int punchInDoneCount = (int) list.stream().filter(v -> Optional.ofNullable(v.getSettlePoints()).orElse(0) > 0).count();
- // 总结算积分
- Integer settlePoints = list.stream().map(v -> Optional.ofNullable(v.getSettlePoints()).orElse(0)).reduce(0, Integer::sum);
- // 打卡率
- BigDecimal punchInRate = BigDecimal.ZERO;
- // 打卡完成率
- BigDecimal punchInDoneRate = BigDecimal.ZERO;
- if (punchInTotalCount != 0) {
- BigDecimal punchInTotalCountVal = BigDecimal.valueOf(punchInTotalCount);
- punchInRate = BigDecimal.valueOf(punchInCount).divide(punchInTotalCountVal, 4, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
- punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(punchInTotalCountVal, 4, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
- }
- StatPiTask statPiTask = null;
- if (StatPeriodEnum.WEEK.equals(statPeriod)) {
- statPiTask = new StatPiTaskWeek();
- } else if (StatPeriodEnum.MONTH.equals(statPeriod)) {
- statPiTask = new StatPiTaskMonth();
- } else if (StatPeriodEnum.YEAR.equals(statPeriod)) {
- statPiTask = new StatPiTaskYear();
- }
- statPiTask.setPunchInTotalCount(punchInTotalCount);
- statPiTask.setPunchInCount(punchInCount);
- statPiTask.setPunchInDoneCount(punchInDoneCount);
- statPiTask.setPunchInRate(punchInRate);
- statPiTask.setPunchInDoneRate(punchInDoneRate);
- statPiTask.setPoints(settlePoints);
- return statPiTask;
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void statNewUser(String statTime) {
- Assert.isNullInBusiness(statTime, "统计日期不能为空");
- // 构建查询的时间范围
- String creationTimeFrom = String.format("%s 00:00:00.000", statTime);
- String creationTimeTo = String.format("%s 23:59:59.999", statTime);
- // 统计
- int newUserCount = userService.countByCondition(creationTimeFrom, creationTimeTo);
- // 数据入库
- StatNewUser addStatNewUser = new StatNewUser();
- addStatNewUser.setStatTime(statTime.toString());
- addStatNewUser.setNewUserCount(newUserCount);
- statNewUserService.insert(addStatNewUser);
- }
- }
|