TodoTask.java 10.6 KB
package cn.fw.dalaran.server.task;

import cn.fw.dalaran.common.constants.Constants;
import cn.fw.dalaran.common.utils.DateUtil;
import cn.fw.dalaran.domain.db.Account;
import cn.fw.dalaran.domain.db.ActivityTheme;
import cn.fw.dalaran.domain.db.LivePool;
import cn.fw.dalaran.domain.db.TodoHistory;
import cn.fw.dalaran.domain.vo.ActivityThemeVo;
import cn.fw.dalaran.rpc.backlog.TodoRpcService;
import cn.fw.dalaran.rpc.backlog.dto.BackLogItemDTO;
import cn.fw.dalaran.rpc.erp.UserRoleRpcService;
import cn.fw.dalaran.rpc.erp.dto.UserInfoDTO;
import cn.fw.dalaran.service.data.AccountService;
import cn.fw.dalaran.service.data.ActivityThemeService;
import cn.fw.dalaran.service.data.LivePoolService;
import cn.fw.dalaran.service.data.TodoHistoryService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kurisu
 * @date 2021-12-02 16:34
 * @description 待办定时任务
 */
@Slf4j
@Component
@ConditionalOnProperty(prefix = "task", name = "switch", havingValue = "on")
@RequiredArgsConstructor
public class TodoTask {

    private final TodoHistoryService todoHistoryService;
    private final TodoRpcService todoRpcService;
    private final AccountService accountService;
    private final ActivityThemeService activityThemeService;
    private final LivePoolService livePoolService;
    private final UserRoleRpcService userRoleRpcService;

    /**
     * 发送待办
     */
    @Scheduled(fixedRate = 15 * 1000, initialDelay = 5 * 1000)
    public void sendTodo() {
        List<TodoHistory> list = todoHistoryService.list(Wrappers.<TodoHistory>lambdaQuery()
                .eq(TodoHistory::getSend, Boolean.FALSE)
                .eq(TodoHistory::getDone, Boolean.FALSE)
                .ge(TodoHistory::getCreateTime, DateUtil.minusDays(new Date(), 7))// 创建时间不超过7天的
        );// 找到需要推送待办的数据项
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        final Map<String, List<TodoHistory>> todoMap = list.stream()
                .collect(Collectors.groupingBy(TodoHistory::getTodoCode));// 根据待办编码分组
        final List<TodoHistory> loginAccount = Optional
                .ofNullable(todoMap.get(Constants.ACCOUNT_INVALID))
                .orElse(new ArrayList<>());
        final List<TodoHistory> checkLive = Optional
                .ofNullable(todoMap.get(Constants.CHECK_LIVE))
                .orElse(new ArrayList<>());
        for (TodoHistory history : loginAccount) {// 处理账号登录待办
            Account account = accountService.getById(history.getDataId());
            if (Objects.isNull(account)) {
                continue;
            }
            BackLogItemDTO dto = new BackLogItemDTO(history.getUserId(), history.getTodoCode(),
                    history.getDataId().toString(), new Date(), history.getShopId());// 构造待办参数
            Map<String, String> dynamicMap = new HashMap<>(4);
            dynamicMap.put("name", account.getType().getName());
            dynamicMap.put("shopName", account.getShopName());
            dynamicMap.put("account", account.getAccount());
            dynamicMap.put("userName", account.getUserName());
            dto.setDynamicMap(dynamicMap);
            if (todoRpcService.push(dto)) {
                history.setSend(Boolean.TRUE);
            }
        }
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (TodoHistory history : checkLive) {// 处理直播审计待办
            final Long themeId = history.getDataId();
            final ActivityTheme theme = activityThemeService.getById(themeId);
            BackLogItemDTO dto = new BackLogItemDTO(history.getUserId(), history.getTodoCode(),
                    themeId.toString(), new Date(), history.getShopId());// 构造待办参数
            Map<String, String> dynamicMap = new HashMap<>(4);
            dynamicMap.put("theme", theme.getTheme());
            dynamicMap.put("startTime", sdf.format(theme.getStartTime()));
            dynamicMap.put("endTime", sdf.format(theme.getEndTime()));
            dto.setDynamicMap(dynamicMap);
            if (todoRpcService.push(dto)) {
                history.setSend(Boolean.TRUE);
            }
        }
        final ArrayList<TodoHistory> result = new ArrayList<>(loginAccount);
        result.addAll(checkLive);
        todoHistoryService.updateBatchById(result);
    }

    /**
     * 完成待办
     */
    @Scheduled(fixedRate = 15 * 1000, initialDelay = 5 * 1000)
    public void completeTodo() {
        List<TodoHistory> list = todoHistoryService.list(Wrappers.<TodoHistory>lambdaQuery()
                .eq(TodoHistory::getSend, Boolean.TRUE)
                .eq(TodoHistory::getDone, Boolean.TRUE)
                .eq(TodoHistory::getTodoDone, Boolean.FALSE)
        );
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (TodoHistory history : list) {
            /*if (Objects.equals(history.getTodoCode(), Constants.ACCOUNT_INVALID)) {// 账号失效待办
                Account account = accountService.getById(history.getDataId());
                if (Objects.isNull(account)) {
                    continue;
                }
            }*/
            BackLogItemDTO dto = new BackLogItemDTO(history.getUserId(), history.getTodoCode(),
                    history.getDataId().toString(), new Date(), history.getShopId());// 构造待办参数
            if (todoRpcService.complete(dto)) {
                history.setTodoDone(Boolean.TRUE);
            }
        }
        todoHistoryService.updateBatchById(list);
    }

    /**
     * 每天都找需要审计的主题
     */
    @Scheduled(fixedRate = 15 * 60 * 1000, initialDelay = 5 * 1000)
    public void sendLiveCheckBacklog() {
        this.sendLiveCheckBacklog(System.currentTimeMillis());
    }

    /**
     * 发送直播审计待办
     *
     * @param timeStamp 指定时间
     */
    public void sendLiveCheckBacklog(Long timeStamp) {
        final List<ActivityTheme> themeList = activityThemeService.lambdaQuery()
                .gt(ActivityTheme::getEndTime, new Date(timeStamp - 7 * 24 * 3600 * 1000))
                .list()
                .stream()
                .filter(item -> {
                    final long timeSub = timeStamp - item.getEndTime().getTime();
                    return 24 * 3600 * 1000 < timeSub && timeSub < 2 * 24 * 3600 * 1000;
                })
                .collect(Collectors.toList());// 找到(理论上)需要审计的主题
        if (CollectionUtils.isEmpty(themeList))
            return;
        final List<LivePool> bestLives = livePoolService.lambdaQuery()
                .in(LivePool::getThemeId, themeList.stream()
                        .map(ActivityTheme::getId)
                        .collect(Collectors.toList())
                )
                .eq(LivePool::getValidLive, 11)
                .list();// 找到主题对应的所有人的最佳直播
        final List<Long> waitCheckThemeIds = bestLives.stream()
                .map(LivePool::getThemeId)
                .distinct()
                .collect(Collectors.toList());// 根据最佳直播分布, 找到(真正)需要审核的主题id集合
        if (CollectionUtils.isEmpty(waitCheckThemeIds))
            return;
        final List<Long> usersInShopIds = accountService.lambdaQuery()
                .in(Account::getId, bestLives.stream()
                        .collect(Collectors.groupingBy(LivePool::getAccountId))
                        .keySet()
                )// 所有账户id
                .list()
                .stream()
                .map(Account::getShopId)
                .distinct()// 祛除重复门店
                .collect(Collectors.toList());// 最佳直播的账户分布在对应的门店id集合
        final List<ActivityThemeVo> themeVos = themeList.stream()
                .filter(item -> waitCheckThemeIds.contains(item.getId()))// 过滤出(真正)需要审核的主题
                .map(ActivityTheme::toVO)
                .collect(Collectors.toList());// 将主题转换成vo
        if (CollectionUtils.isEmpty(themeVos))
            return;
        List<TodoHistory> hasSaveTodo = todoHistoryService.lambdaQuery()
                .eq(TodoHistory::getTodoCode, Constants.CHECK_LIVE)
                .in(TodoHistory::getDataId, themeVos.stream()
                        .map(ActivityThemeVo::getId)
                        .collect(Collectors.toList())
                )
                .list();// 查询需要审核的主题已经保存的待办信息
        ArrayList<TodoHistory> collect = usersInShopIds
                .stream()
                .map(item -> {// 遍历每个门店
                    TodoHistory todo = new TodoHistory();
                    List<UserInfoDTO> users = userRoleRpcService.getUsers(item, Constants.ZBSJ_ROLE_CODE);// 获取门店拥有'直播审计'角色的人
                    if (!users.isEmpty()) {
                        todo.setSend(false);
                        todo.setDone(false);
                        todo.setTodoDone(false);
                        todo.setTodoCode(Constants.CHECK_LIVE);
                        todo.setDataId(themeVos.stream()
                                .filter(item1 -> item1.getShopIds().contains(item))
                                .collect(Collectors.toList())
                                .get(0)
                                .getId()
                        );
                        todo.setShopId(item);
                        todo.setUserId(users.get(0).getUserId());
                    }
                    return todo;
                })
                .filter(item -> Objects.nonNull(item.getTodoCode()))
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(TodoHistory::getRemoveDuplicatesCondition))), ArrayList::new)
                );
        if (!Objects.equals(hasSaveTodo.size(), 0) && Objects.equals(collect.size(), hasSaveTodo.size()))
            return;
        List<Long> themeIds = hasSaveTodo.stream()
                .map(TodoHistory::getDataId)
                .collect(Collectors.toList());
        todoHistoryService.saveBatch(collect.stream()
                .filter(item -> !themeIds.contains(item.getDataId()))
                .collect(Collectors.toList())
        );// 保存待办
    }

}