package jnpf.attendance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jnpf.attendance.dto.AttendanceUserGroupVo;
import jnpf.attendance.dto.AttendanceUserListGroupVO;
import jnpf.attendance.mapper.*;
import jnpf.attendance.service.*;
import jnpf.attendance.service.handle.notice.AttendanceNoticeHandler;
import jnpf.authority.FtbAuthorityApi;
import jnpf.authority.service.FtbPermissionOrganizeService;
import jnpf.authority.utils.PermissionsUtils;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.service.SuperServiceImpl;
import jnpf.base.vo.PageListVO;
import jnpf.constants.AttendancePermissionConstant;
import jnpf.constants.RedisConstant;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.entity.*;
import jnpf.entity.attendance.AppointPermission;
import jnpf.entity.attendance.AttendanceLocationSetting;
import jnpf.entity.attendance.FtbAttendanceLineSchedulingConfig;
import jnpf.enums.attendance.AttendanceNoticeEnum;
import jnpf.enums.attendance.GroupUserTypeEnum;
import jnpf.enums.attendance.PermissionTypeEnum;
import jnpf.enums.attendance.v2.FuncCodingEnum;
import jnpf.exception.HandleException;
import jnpf.exception.LoginException;
import jnpf.exception.QueryException;
import jnpf.model.attendance.dto.*;
import jnpf.model.attendance.model.AttendanceNoticeModel;
import jnpf.model.attendance.model.RuleChangeNoticeModel;
import jnpf.model.attendance.model.UserChangeNoticeModel;
import jnpf.model.attendance.vo.*;
import jnpf.model.attendance.vo.attendance.GroupLockVo;
import jnpf.model.authority.vo.role.FtbPermissionRoleIdentificationVO;
import jnpf.model.personnels.dto.staff.roster.FtbPersonnelsStaffRosterDto;
import jnpf.model.personnels.req.roster.StaffRosterListReq;
import jnpf.permission.V2OrganizeApi;
import jnpf.permission.V2UserApi;
import jnpf.permission.dto.v2.organzie.QueryOrganizeListTargetTypesDTO;
import jnpf.permission.eum.v2.NodeTypeEnum;
import jnpf.permission.eum.v2.OrganizeCategoryEnums;
import jnpf.permission.eum.v2.UserWorkStatusEnums;
import jnpf.permission.vo.store.StoreBaseListInfo;
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
import jnpf.permission.vo.v2.organzie.OrganizeManagerFilterNodeVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.FtbPersonnelsRosterManagerApi;
import jnpf.util.*;
import jnpf.util.mapper.MybatisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static jnpf.constants.RedisConstant.ATTENDANCE_BASE_SETTING_CACHE_KEY;

/**
 * 打卡服务实现
 *
 * @author yanwenfu
 * @create 2023-11-21
 */
@Service
@Slf4j
public class AttendanceGroupServiceImpl extends SuperServiceImpl<AttendanceGroupMapper, AttendanceGroup> implements AttendanceGroupService {

    private final static String GROUP_TOP_PARENT_ID = "000000";
    /**
     * 考勤组id threadlocal
     */
    private static final ThreadLocal<List<String>> GROUP_ID_LOCAL = ThreadLocal.withInitial(ArrayList::new);
    @Resource
    private AttendanceMachineManageMapper attendanceMachineManageMapper;
    @Resource
    private AttendanceGroupMapper attendanceGroupMapper;
    @Resource
    private UserProvider userProvider;
    @Resource
    private AttendanceGroupUserMapper attendanceGroupUserMapper;
    @Resource
    private AttendanceManagerPermissionMapper attendanceManagerPermissionMapper;
    @Resource
    private AttendanceApprovalSettingService attendanceApprovalSettingService;
    @Resource
    private AttendanceApprovalSettingMapper attendanceApprovalSettingMapper;
    @Resource
    private AttendanceSuperAdminService attendanceSuperAdminService;
    @Autowired
    private AttendanceBaseSettingService attendanceBaseSettingService;
    @Autowired
    private AttendanceShiftSettingService attendanceShiftSettingService;
    @Autowired
    private AttendanceFestivalSettingService attendanceFestivalSettingService;
    @Autowired
    private AttendanceHolidaySettingService attendanceHolidaySettingService;
    @Autowired
    private AttendanceLocationSettingService attendanceLocationSettingService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private AttenceMachineService attenceMachineService;
    @Autowired
    private AttendanceMachineManageService attendanceMachineManageService;
    @Resource
    private AttendanceUserService attendanceUserService;
    @Resource
    private AttendanceDailyRuleService attendanceDailyRuleService;
    @Resource
    private AttendanceClockInService attendanceClockInService;
    @Autowired
    private AttendanceDayStatisticsService attendanceDayStatisticsService;
    @Autowired
    private AttendanceNoticeHandler attendanceNoticeHandler;
    @Resource
    private PermissionDictMapper permissionDictMapper;
    @Resource
    private V2UserApi v2UserApi;
    @Resource
    private V2OrganizeApi v2OrganizeApi;
    @Resource
    private FtbAuthorityApi ftbAuthorityApi;
    @Autowired
    private FtbPermissionOrganizeService ftbPermissionOrganizeService;
    @Autowired
    @Lazy
    private PermissionsUtils permissionsUtils;
    @Autowired
    private AttendanceLineSchedulingConfigService lineSchedulingConfigService;
    @Autowired
    private FtbPersonnelsRosterManagerApi ftbPersonnelsRosterManagerApi;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int save(SaveAttendanceGroupDto saveAttendanceGroupDto) throws HandleException {
        AttendanceGroup byGroupName = MybatisUtil.findByFiled(attendanceGroupMapper, AttendanceGroup::getGroupName, saveAttendanceGroupDto.getGroupName(), true);
        /* 根据名称查找考勤组*/
        AttendanceGroup attendanceGroup = JsonUtil.getJsonToBean(saveAttendanceGroupDto, AttendanceGroup.class);
        /*id为空则新增考勤组*/
        if (saveAttendanceGroupDto.getId() == null) {
            if (byGroupName != null) {
//                throw new HandleException("该考勤组已存在!");
                return -1;
            }
            String uuId = RandomUtil.uuId();
            attendanceGroup.setId(uuId);
            /* 基础字段*/
            attendanceGroup.setCreatorUserId(userProvider.get().getUserId());
            attendanceGroup.setCreatorTime(new Date());
            attendanceGroup.setParentId(StrUtil.isBlank(saveAttendanceGroupDto.getParentId()) ? GROUP_TOP_PARENT_ID : saveAttendanceGroupDto.getParentId());
            List<AttendanceGroup> group = new ArrayList<>();
            group.add(attendanceGroup);
            /* 找到父级节点，维护考勤组层级编码*/
            recursionParent(attendanceGroup.getParentId(), group);
            String levelCode = CollectionUtil.join(group.stream().map(AttendanceGroup::getId).collect(Collectors.toList()), "#");
            attendanceGroup.setLevelCode(levelCode);
            List<AttendanceGroup> reverse = CollectionUtil.reverse(group);
            attendanceGroup.setDetailName(CollectionUtil.join(reverse.stream().map(AttendanceGroup::getGroupName).collect(Collectors.toList()), "/"));
            attendanceGroupMapper.insert(attendanceGroup);

            /* 新增考勤组审批设置模版*/
            attendanceApprovalSettingService.addTemplateSetting(uuId);
            return 0;
        }
        /*id不为空则修改考勤组信息*/
        if (byGroupName != null && !byGroupName.getId().equals(saveAttendanceGroupDto.getId())) {
//            throw new HandleException("该考勤组已存在!");
            return -1;
        }
        /* 基础字段*/
        attendanceGroup.setLastModifyTime(new Date());
        attendanceGroup.setLastModifyUserId(userProvider.get().getUserId());
        attendanceGroupMapper.updateById(attendanceGroup);
        return 0;
    }

    @Override
    public List<String> getGroupIdByUserId(String userId, Date applyStart, Date applyEnd) throws HandleException {
        List<String> userIds = CollUtil.newArrayList(userId);
        List<AttendanceGroupUser> users = attendanceUserService.queryByUsersIds(userIds);
        if (CollUtil.isEmpty(users)) {
            log.error("未查询到所有考勤组人员信息,{}", JSON.toJSONString(userIds));
            throw new HandleException("未查询到所有考勤组人员信息");
        }
        Date start = Objects.isNull(applyStart) ? DateUtil.getDayBegin() : applyStart;
        Date end = Objects.isNull(applyEnd) ? DateUtil.getDayEnd() : applyEnd;
        return getGroupIdByUserId(users, start, end);
    }

    @Override
    public List<String> getGroupIdByUserId(List<AttendanceGroupUser> users, Date start, Date end) {
        return users.stream().filter(user -> {
            List<SecondmentDateVo> secondmentDateVos = StringUtil.isEmpty(user.getTimeJson()) ? null : JsonUtil.getJsonToList(user.getTimeJson(), SecondmentDateVo.class);
            if (user.getUserGroupType() == 2) {
                if (CollUtil.isEmpty(secondmentDateVos)) {
                    return Boolean.FALSE;
                }
                for (SecondmentDateVo dateVo : secondmentDateVos) {
                    return DateDetail.checkTimeBetween(start, dateVo.getStartTime(), dateVo.getEndTime())
                            || DateDetail.checkTimeBetween(end, dateVo.getStartTime(), dateVo.getEndTime())
                            || DateDetail.checkTimeBetween(dateVo.getStartTime(), start, end)
                            || DateDetail.checkTimeBetween(dateVo.getEndTime(), start, end);
                }
            } else {
                if (CollUtil.isEmpty(secondmentDateVos)) {
                    return Boolean.TRUE;
                }
                for (SecondmentDateVo dateVo : secondmentDateVos) {
                    return !(DateDetail.checkTimeBetween(start, dateVo.getStartTime(), dateVo.getEndTime())
                            || DateDetail.checkTimeBetween(end, dateVo.getStartTime(), dateVo.getEndTime())
                            || DateDetail.checkTimeBetween(dateVo.getStartTime(), start, end)
                            || DateDetail.checkTimeBetween(dateVo.getEndTime(), start, end));
                }
            }
            return Boolean.FALSE;
        }).map(AttendanceGroupUser::getGroupId).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id, String parentId) {
        /* 直接删除所有子考勤组*/
        /* 需要删除的子考勤组id集合*/
        QueryWrapper<AttendanceGroup> queryChildGroupWrapper = new QueryWrapper<>();
        queryChildGroupWrapper.lambda()
                .like(AttendanceGroup::getLevelCode, id);
        List<AttendanceGroup> attendanceGroups = attendanceGroupMapper.selectList(queryChildGroupWrapper);
        List<String> deleteGroupIds = attendanceGroups.stream().map(AttendanceGroup::getId).collect(Collectors.toList());

        /* 查询被删除考勤组下所有成员*/
        QueryWrapper<AttendanceGroupUser> groupUserQueryWrapper = new QueryWrapper<>();
        groupUserQueryWrapper.lambda()
                .in(AttendanceGroupUser::getGroupId, deleteGroupIds)
                .eq(AttendanceGroupUser::getDeleteMark, Boolean.FALSE)
                .eq(AttendanceGroupUser::getType, GroupUserTypeEnum.CUR.getCode());
        List<AttendanceGroupUser> groupUserList = attendanceGroupUserMapper.selectList(groupUserQueryWrapper);
        // 查询被删除考勤组和移动新成员的考勤组对应的考勤机配置
        attendanceMachineManageService.removeMachineRelation(groupUserList.stream().map(AttendanceGroupUser::getUserId).collect(Collectors.toList()), parentId, deleteGroupIds);
        if (CollUtil.isEmpty(groupUserList)) {
            deleteGroup(deleteGroupIds);
            return;
        }

        /* 删除本组以及子考勤组所关联成员及借调数据*/
        List<String> collect = groupUserList.stream().map(AttendanceGroupUser::getUserId).distinct().collect(Collectors.toList());
        LambdaUpdateWrapper<AttendanceGroupUser> in = new UpdateWrapper<AttendanceGroupUser>().lambda()
                .eq(AttendanceGroupUser::getDeleteMark, Boolean.FALSE)
                .in(AttendanceGroupUser::getUserId, collect);
        AttendanceGroupUser deleteGroupUser = new AttendanceGroupUser();
        deleteGroupUser.setDeleteMark(1);
        String nullJson = JsonUtil.getJsonToBean(new ArrayList<>(), String.class);
        deleteGroupUser.setTimeJson(nullJson);
        deleteGroupUser.setRemoveTime(new Date());
        attendanceGroupUserMapper.update(deleteGroupUser, in);

        /* 删除审批配置配置*/
        UpdateWrapper<AttendanceApprovalSetting> deleteWrapper = new UpdateWrapper<>();
        deleteWrapper.lambda()
                .in(AttendanceApprovalSetting::getGroupId, deleteGroupIds);
        attendanceApprovalSettingMapper.delete(deleteWrapper);
        /* 移除考勤机*/
        Map<String, List<AttendanceGroupUser>> userGroupByGroupRuleMap = groupUserList.stream().collect(Collectors.groupingBy(AttendanceGroupUser::getGroupId));
        userGroupByGroupRuleMap.forEach((k, v) -> {
            log.error("删除考勤组，清除规则的考勤组【{}】用户集合为{}", k, JSON.toJSONString(v));
            List<String> userIds = v.stream().map(AttendanceGroupUser::getUserId).collect(Collectors.toList());
            /* 移除考勤规则*/
            attendanceDailyRuleService.clearGroupRule(k, userIds);
        });
        deleteGroup(deleteGroupIds);
        /* 成员移动到所选考勤组考勤组*/
        List<String> userIds = groupUserList.stream().map(AttendanceGroupUser::getUserId).collect(Collectors.toList());
        if (StrUtil.isNotBlank(parentId) && CollectionUtil.isNotEmpty(groupUserList)) {
            List<AttendanceGroupUser> addGroupUserList = new ArrayList<>();
            for (String userId : userIds) {
                if (CollectionUtil.isNotEmpty(addGroupUserList)) {
                    /* 避免用户操作太快，幂等问题*/
                    List<String> addUserIds = addGroupUserList.stream().map(AttendanceGroupUser::getUserId).collect(Collectors.toList());
                    if (addUserIds.contains(userId)) {
                        continue;
                    }
                }
                AttendanceGroupUser groupUser = new AttendanceGroupUser();
                groupUser.setId(RandomUtil.uuId());
                groupUser.setGroupId(parentId);
                groupUser.setUserId(userId);
                groupUser.setType(GroupUserTypeEnum.CUR.getCode());
                groupUser.setUserGroupType(GroupUserTypeEnum.CUR.getCode());
                groupUser.setCreatorTime(new Date());
                groupUser.setCreatorUserId(UserProvider.getLoginUserId());
                addGroupUserList.add(groupUser);
            }
            attendanceUserService.saveBatch(addGroupUserList);
            attendanceDayStatisticsService.userJoinHandleData(UserProvider.getUser().getTenantId(), parentId, userIds);
            attendanceDailyRuleService.addUserFixedHandle(parentId, userIds);
            // V1.8.1批量移动考勤组权限
            attendanceManagerPermissionMapper.updateBatchUserGroupManagerPermission(userIds, id, parentId);
            sendNoticeByUserChange(parentId, userIds, UserProvider.getUser().getTenantId(), AttendanceNoticeEnum.GROUP_CHANGE_REMOVE_JOIN_GROUP);
            userIds.forEach(userId -> attendanceClockInService.generateRepairNumForUser(parentId, userId, 1));
            return;
        }
        sendNoticeByUserChange(null, userIds, UserProvider.getUser().getTenantId(), AttendanceNoticeEnum.REMOVE_USER_REMOVE_GROUP);
    }

    /**
     * 删除考勤组以及子考勤组
     *
     * @param deleteGroupIds 要删除的考勤组ID列表
     */
    private void deleteGroup(List<String> deleteGroupIds) {
        // 使用更新条件包装器来准备删除条件
        UpdateWrapper<AttendanceGroup> updateWrapper = new UpdateWrapper<>();
        // 通过lambda表达式设置条件，筛选出需要删除的考勤组ID
        updateWrapper.lambda()
                .in(AttendanceGroup::getId, deleteGroupIds);
        // 准备更新的数据对象，设置标志位和其他相关字段
        AttendanceGroup update = new AttendanceGroup();
        update.setDeleteMark(1); // 设置删除标志位为1，表示已删除
        update.setDeleteUserId(userProvider.get().getUserId()); // 设置执行删除操作的用户ID
        update.setLastModifyTime(new Date()); // 设置最后修改时间为当前时间
        // 执行更新操作，将符合条件的考勤组标记为已删除
        attendanceGroupMapper.update(update, updateWrapper);
    }


    private void sendNoticeByUserChange(String joinGroupId, List<String> userIds, String tenantId, AttendanceNoticeEnum attendanceNoticeEnum) {
        UserChangeNoticeModel userChangeNoticeModel = new UserChangeNoticeModel();
        userChangeNoticeModel.setJoinGroupId(joinGroupId);
        userChangeNoticeModel.setUserIds(userIds);
        userChangeNoticeModel.setTenantId(tenantId);
        userChangeNoticeModel.setAttendanceNoticeEnum(attendanceNoticeEnum);
        attendanceNoticeHandler.send(userChangeNoticeModel);
    }

    @Override
    public void exchangeGroupStatus(AttendanceGroupStatusDto dto) {
        AttendanceGroup attendanceGroup = new AttendanceGroup();
        attendanceGroup.setId(dto.getGroupId());
        if (Objects.nonNull(dto.getLineSchedulingSetting())) {
            attendanceGroup.setLineSchedulingSetting(dto.getLineSchedulingSetting());
            attendanceGroupMapper.updateById(attendanceGroup);
            return;
        }
        attendanceGroup.setHolidaySetting(dto.getHolidaySetting());
        attendanceGroup.setFestivalSetting(dto.getFestivalSetting());
        attendanceGroup.setLeaveSetting(dto.getLeaveSetting());
        attendanceGroup.setGpsEnable(dto.getGpsEnable());
        attendanceGroup.setWifiEnable(dto.getWifiEnable());
        attendanceGroup.setMachineEnable(dto.getMachineEnable());
        AttendanceGroupStatusDto attendanceGroupNew = groupSettingStatus(dto.getGroupId(), Boolean.TRUE);
        if (Objects.nonNull(dto.getBaseSetting())) {
            if (Objects.equals(1, dto.getBaseSetting())) {
                attendanceBaseSettingService.initBaseSetting(dto.getGroupId());
            }
            attendanceGroup.setBaseSetting(dto.getBaseSetting());
            AttendanceBaseSettingVo one = attendanceBaseSettingService.getOne(dto.getGroupId());
            attendanceBaseSettingService.changeStatus(dto.getGroupId(), dto.getBaseSetting(), one);
            attendanceGroupMapper.updateById(attendanceGroup);
            return;
        }
        if (Objects.nonNull(dto.getLeaveSetting())) {
//                if (Objects.equals(1, dto.getLeaveSetting())) {
//                    try {
//                        attendanceApprovalService.initializationLeaveSetting(dto.getGroupId());
//                    } catch (HandleException e) {
//                        e.printStackTrace();
//                        log.error("初始化考勤组[{}]请假配置异常", dto.getGroupId());
//                    }
//                }
            attendanceGroupMapper.updateById(attendanceGroup);
        }
        if (Objects.nonNull(dto.getAttendanceClassSetting())) {
            if (Objects.equals(1, dto.getAttendanceClassSetting())) {
                attendanceShiftSettingService.initShiftSetting(dto.getGroupId());
            }
            attendanceGroup.setAttendanceClassSetting(dto.getAttendanceClassSetting());
            AttendanceShiftSettingVo byGroupId = attendanceShiftSettingService.findByGroupId(dto.getGroupId());
            attendanceGroupMapper.updateById(attendanceGroup);
            attendanceShiftSettingService.changeStatus(dto.getGroupId(), dto.getAttendanceClassSetting(), byGroupId);
            return;
        }
        if (Objects.nonNull(dto.getFestivalSetting())) {
            if (Objects.equals(1, dto.getFestivalSetting())) {
                attendanceFestivalSettingService.initFestivalSetting(dto.getGroupId());
            }
            attendanceGroupMapper.updateById(attendanceGroup);
            return;
        }
        if (Objects.nonNull(dto.getHolidaySetting())) {
            if (Objects.equals(1, dto.getHolidaySetting())) {
                attendanceHolidaySettingService.initHolidaySetting(dto.getGroupId());
            }
            attendanceGroupMapper.updateById(attendanceGroup);
            return;
        }
        String parentGroupId = attendanceGroupMapper.getParentGroupId(dto.getGroupId());
        if (Objects.equals(1, dto.getAttendancePointsSetting())) {
            // 开启配置
            attendanceLocationSettingService.initLocationSetting(dto.getGroupId());
            attendanceGroup.setAttendancePointsSetting(dto.getAttendancePointsSetting());
            attendanceGroupMapper.updateById(attendanceGroup);
            // 查询父级考勤机的配置
            List<AttendanceLocationSetting> locationSettings = getGroupLocationSettings(parentGroupId);
            machineDeal(locationSettings, dto.getGroupId(), ConstantUtil.CAL_REDUCE);
        } else if (Objects.equals(0, dto.getAttendancePointsSetting())) {
            attendanceGroup.setAttendancePointsSetting(dto.getAttendancePointsSetting());
            attendanceGroupMapper.updateById(attendanceGroup);
            // 关闭配置, 不移除自定义配置考勤机中的成员, 新增本级及继承子级的考勤组成员到父级考勤机中
            List<AttendanceLocationSetting> locationSettings = getGroupLocationSettings(parentGroupId);
            machineDeal(locationSettings, dto.getGroupId(), ConstantUtil.CAL_ADD);
        }
        if (Objects.nonNull(dto.getAttendancePointsSetting())) {
            AttendanceGroup attendanceGroupOld = getEnableLocationSetting(parentGroupId);
            if (attendanceGroupOld != null && !attendanceGroupNew.getGpsEnable().equals(attendanceGroupOld.getGpsEnable())) {
                List<String> addressesList = getAddressesList(dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getId() : attendanceGroupNew.getGroupId(), 1);
                List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
                selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, attendanceGroupNew.getGpsEnable(), dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getGpsEnable() : attendanceGroupNew.getGpsEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_GPS_SWIFT));
            }
            if (attendanceGroupOld != null && !attendanceGroupNew.getWifiEnable().equals(attendanceGroupOld.getWifiEnable())) {
                List<String> addressesList = getAddressesList(dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getId() : attendanceGroupNew.getGroupId(), 2);
                List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
                selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, attendanceGroupNew.getWifiEnable(), dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getWifiEnable() : attendanceGroupNew.getWifiEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_WIFI_SWIFT));
            }
            if (attendanceGroupOld != null && !attendanceGroupNew.getMachineEnable().equals(attendanceGroupOld.getMachineEnable())) {
                List<String> addressesList = getAddressesList(dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getId() : attendanceGroupNew.getGroupId(), 3);
                List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
                selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, attendanceGroupNew.getMachineEnable(), dto.getAttendancePointsSetting().equals(0) ? attendanceGroupOld.getMachineEnable() : attendanceGroupNew.getMachineEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_KQJ_SWIFT));
            }
        }
        if (Objects.nonNull(dto.getGpsEnable())) {
            attendanceLocationSettingService.changeStatus(dto.getGroupId(), 1, dto.getGpsEnable());
            attendanceGroupMapper.updateById(attendanceGroup);
            List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
            List<String> addressesList = getAddressesList(dto.getGroupId(), 1);
            selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, null, dto.getGpsEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_GPS_SWIFT));
        }
        if (Objects.nonNull(dto.getWifiEnable())) {
            attendanceLocationSettingService.changeStatus(dto.getGroupId(), 2, dto.getWifiEnable());
            attendanceGroupMapper.updateById(attendanceGroup);
            List<String> addressesList = getAddressesList(dto.getGroupId(), 2);
            List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
            selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, null, dto.getWifiEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_WIFI_SWIFT));
        }
        if (Objects.nonNull(dto.getMachineEnable())) {
            attendanceLocationSettingService.changeStatus(dto.getGroupId(), 3, dto.getMachineEnable());
            attendanceGroupMapper.updateById(attendanceGroup);
            List<String> addressesList = getAddressesList(dto.getGroupId(), 3);
            List<String> selfAndChildrenGroupIds = getSelfAndChildrenGroupIds(dto.getGroupId(), 2);
            selfAndChildrenGroupIds.forEach(itemGroupId -> sendNoticeItem(itemGroupId, null, dto.getMachineEnable(), addressesList, AttendanceNoticeEnum.RULE_CHANGE_KQJ_SWIFT));
        }
    }

    private List<String> getAddressesList(String groupId, Integer type) {
        List<String> addressesList = new ArrayList<>();
        List<AttendanceLocationSettingVo> list = attendanceLocationSettingService.findList(groupId, type);
        if (CollUtil.isNotEmpty(list)) {
            list.forEach(vo -> {
                StringBuilder sb = new StringBuilder();
                if (type.equals(1)) {
                    sb.append(vo.getName()).append("（").append(vo.getClockRange()).append("米）").append("：").append(vo.getAddress());
                } else {
                    sb.append(vo.getName());
                }
                addressesList.add(sb.toString());
            });
        }
        return addressesList;
    }


    private void sendNoticeItem(String groupId, Object oldValue, Object newValue, List<String> addressList, AttendanceNoticeEnum attendanceNoticeEnum) {
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        RuleChangeNoticeModel ruleChangeNoticeModel = new RuleChangeNoticeModel();
        ruleChangeNoticeModel.setIsAdmin(Boolean.FALSE);
        ruleChangeNoticeModel.setOldValue(oldValue);
        ruleChangeNoticeModel.setNewValue(newValue);
        ruleChangeNoticeModel.setAddressList(addressList);
        ruleChangeNoticeModel.setGroupId(groupId);
        ruleChangeNoticeModel.setTenantId(UserProvider.getUser().getTenantId());
        ruleChangeNoticeModel.setAttendanceNoticeEnum(attendanceNoticeEnum);
        attendanceNoticeHandler.send(ruleChangeNoticeModel);
        ruleChangeNoticeModel.setIsAdmin(Boolean.TRUE);
        attendanceNoticeHandler.send(ruleChangeNoticeModel);
    }

    private void machineDeal(List<AttendanceLocationSetting> locationSettings, String groupId, String method) {

        if (!locationSettings.isEmpty()) {
            // 查询本级和继承自己的考勤组成员
            List<String> userIdList = getSelfAndChildrenMembers(groupId);
            if (!userIdList.isEmpty()) {
                if (method.equals(ConstantUtil.CAL_REDUCE)) {
                    locationSettings.forEach(locationSetting -> attenceMachineService.deleteUserList(locationSetting.getFactoryCode(), locationSetting.getAddress(), userIdList));
                } else {
                    locationSettings.forEach(locationSetting -> {
                        userIdList.forEach(userId -> {
                            attenceMachineService.sendUserToMachine(locationSetting.getFactoryCode(), userId, locationSetting.getAddress());
                        });
                    });
                }
            }
        }
    }

    private List<AttendanceLocationSetting> getGroupLocationSettings(String groupId) {

        Map<String, List<AttendanceLocationSetting>> locationSettingMap = attendanceLocationSettingService.getEnableLocationSetting(Stream.of(groupId).collect(Collectors.toList()));
        return locationSettingMap.get(groupId).stream().filter(v -> v.getType().equals(ConstantUtil.DEVICE_MACHINE)).collect(Collectors.toList());
    }

    @Override
    public List<String> getSelfAndChildrenGroupIds(String groupId, Integer settingType) {
        List<GroupNodeVo> list = attendanceGroupMapper.getSelfAndChildrenGroup(groupId);
        List<String> levelCodes = CollUtil.newArrayList();
        if (Objects.equals(settingType, 1)) {
            levelCodes.addAll(list.stream().filter(vo -> Objects.equals(vo.getBaseSetting(), 1) && !vo.getLevelCode().startsWith(groupId)).map(GroupNodeVo::getLevelCode).collect(Collectors.toList()));
        } else if (Objects.equals(settingType, 2)) {
            levelCodes.addAll(list.stream().filter(vo -> Objects.equals(vo.getAttendancePointsSetting(), 1) && !vo.getLevelCode().startsWith(groupId)).map(GroupNodeVo::getLevelCode).collect(Collectors.toList()));
        } else if (Objects.equals(settingType, 3)) {
            levelCodes.addAll(list.stream().filter(vo -> Objects.equals(vo.getAttendanceClassSetting(), 1) && !vo.getLevelCode().startsWith(groupId)).map(GroupNodeVo::getLevelCode).collect(Collectors.toList()));
        }
        list = list.stream().filter(vo -> levelCodes.stream().noneMatch(levelCode -> vo.getLevelCode().endsWith(levelCode))).collect(Collectors.toList());
        return list.stream().map(GroupNodeVo::getId).collect(Collectors.toList());
    }

    @Override
    public List<String> getSelfAndChildrenMembers(String groupId) {

        // 查询本组及子组考勤组
        List<GroupNodeVo> list = attendanceGroupMapper.getSelfAndChildrenGroup(groupId);
        GroupNodeVo groupNode = list.stream().filter(v -> v.getId().equals(groupId)).findFirst().orElse(null);
        assert groupNode != null;
        // 生成树
        List<GroupNodeVo> tree = getGroupTree(list, groupNode);
        // 遍历树获取考勤组id
        List<String> groupIdList = new ArrayList<>();
        getGroupIdList(tree, groupIdList);
        // 查询考勤组成员
        if (groupIdList.isEmpty()) {
            return new ArrayList<>();
        }
        return attendanceGroupUserMapper.getGroupUserListByIds(groupIdList);
    }

    private List<GroupNodeVo> getGroupTree(List<GroupNodeVo> list, GroupNodeVo groupNode) {

        List<GroupNodeVo> tree = new ArrayList<>();
        for (GroupNodeVo item : list) {
            if (item.getPid().equals(groupNode.getPid())) {
                tree.add(item);
            }
            // 寻找子节点
            for (GroupNodeVo treeNode : list) {
                if (treeNode.getPid().equals(item.getId())) {
                    if (treeNode.getAttendancePointsSetting().equals(ConstantUtil.NUM_FALSE)) {
                        item.getChildren().add(treeNode);
                    }
                }
            }
        }
        return tree;
    }

    private void getGroupIdList(List<GroupNodeVo> list, List<String> groupIdList) {

        if (!list.isEmpty()) {
            for (GroupNodeVo groupNode : list) {
                groupIdList.add(groupNode.getId());
                getGroupIdList(groupNode.getChildren(), groupIdList);
            }
        }
    }

    /**
     * 查询考勤组管理列表
     *
     * @param groupName 考勤组名称
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> queryList(String groupName) {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(AttendanceGroup::getDeleteMark, 0)
                .like(StringUtil.isNotEmpty(groupName),
                        AttendanceGroup::getGroupName,
                        groupName);
        List<AttendanceGroup> attendanceGroupList = attendanceGroupMapper.selectList(queryWrapper);
        return JsonUtil.getJsonToList(attendanceGroupList, AttendanceGroupVo.class);
    }

    /**
     * 查询考勤组管理列表
     *
     * @param groupName 考勤组名称
     * @return List<AttendanceGroupVo>
     */
    public List<AttendanceGroup> queryList(String groupName, List<String> orgIds) {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(AttendanceGroup::getDeleteMark, 0)
                .in(StringUtil.isNotEmpty(orgIds),
                        AttendanceGroup::getOrgId, orgIds)
                .like(StringUtil.isNotEmpty(groupName),
                        AttendanceGroup::getGroupName,
                        groupName);
        return attendanceGroupMapper.selectList(queryWrapper);
    }

    @Override
    public List<AttendanceGroup> queryListIncludeDeleteByIds(List<String> groupIds) {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(StringUtil.isNotEmpty(groupIds),
                        AttendanceGroup::getId, groupIds);
        return attendanceGroupMapper.selectList(queryWrapper);
    }

    @Override
    public List<AttendanceGroup> queryListByIds(List<String> groupIds) {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(AttendanceGroup::getDeleteMark, 0)
                .in(StringUtil.isNotEmpty(groupIds),
                        AttendanceGroup::getId, groupIds);

        return attendanceGroupMapper.selectList(queryWrapper);
    }

    @Override
    public List<AttendanceGroup> queryAllListByIds() {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda();
        return attendanceGroupMapper.selectList(queryWrapper);
    }

    /**
     * 查询我管理的考勤组
     *
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> queryManagerGroupList(String keyword) {
        String userId = userProvider.get().getUserId();
        Boolean sysAdmin = userProvider.get().getIsAdministrator();
        if (attendanceSuperAdminService.isSuperAdmin(userId)
                || sysAdmin
        ) {
            /* 如果是考勤超级管理员、则直接返回所有考勤组*/
            QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(AttendanceGroup::getDeleteMark, 0);
            return queryList(keyword);
        }
        /* 返回我管理的考勤组*/
        List<AttendanceGroup> attendanceGroupList = attendanceGroupMapper.queryManagerGroupList(userId, keyword);
        return JsonUtil.getJsonToList(attendanceGroupList, AttendanceGroupVo.class);
//        if (CollectionUtil.isEmpty(attendanceGroupList)) {
//            return new ArrayList<>();
//        }
//        List<String> levelCodeList = attendanceGroupList.stream().map(AttendanceGroup::getLevelCode).collect(Collectors.toList());
//
//        List<String> groupIdList = new ArrayList<>();
//        for (String levelCode : levelCodeList) {
//            List<String> parentIdsByLevelCode = getParentIdsByLevelCode(levelCode, true);
//            groupIdList.addAll(parentIdsByLevelCode);
//        }
//        List<AttendanceGroupVo> allGroupVoList = attendanceManagerPermissionMapper.queryGroupVoInGroupIds(groupIdList);
    }

    /**
     * 根据考勤组名称模糊查询考勤组列表（带权限控制）
     *
     * @param groupName 考勤组名称（支持模糊查询）
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> searchGroupByName(String groupName) {
        Boolean sysAdmin = userProvider.get().getIsAdministrator();
        if (sysAdmin) {
            /* 超级管理员：返回所有匹配的考勤组 */
            return queryList(groupName);
        }

        /* 普通用户：只返回有管理权限且名称匹配的考勤组 */
        List<StoreBaseListInfo> listActionResult = ftbAuthorityApi.authStoreBaseListInfo();
        List<AttendanceGroup> attendanceGroupList = queryList(groupName, listActionResult.stream().map(StoreBaseListInfo::getId).collect(Collectors.toList()));
        return JsonUtil.getJsonToList(attendanceGroupList, AttendanceGroupVo.class);
    }

    /**
     * 查询考勤组下拉列表
     */
    @Override
    public List<AttendanceGroup> queryDropList() {
        QueryWrapper<AttendanceGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(AttendanceGroup::getDeleteMark, 0);
        return attendanceGroupMapper.selectList(queryWrapper);
    }

    @Override
    public AttendanceGroup queryByGroupId(String groupId) {
        LambdaQueryWrapper<AttendanceGroup> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AttendanceGroup::getDeleteMark, 0);
        queryWrapper.eq(AttendanceGroup::getId, groupId);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    /**
     * 查询我所在的考勤组
     *
     * @return List<AttendanceGroup>
     */
    @Override
    public List<AttendanceGroup> queryMyGroups() {
        String loginUserId = UserProvider.getLoginUserId();
        QueryWrapper<AttendanceGroupUser> groupUserQueryWrapper = new QueryWrapper<>();
        groupUserQueryWrapper.lambda()
                .eq(AttendanceGroupUser::getUserId, loginUserId);
        List<AttendanceGroupUser> groupUserList = attendanceGroupUserMapper.selectList(groupUserQueryWrapper);
        if (CollectionUtil.isEmpty(groupUserList)) {
            return new ArrayList<>();
        }
        QueryWrapper<AttendanceGroup> groupQueryWrapper = new QueryWrapper<>();
        groupQueryWrapper.lambda()
                .in(AttendanceGroup::getId, groupUserList.stream().map(AttendanceGroupUser::getGroupId).collect(Collectors.toList()))
                .eq(AttendanceGroup::getDeleteMark, 0);
        return attendanceGroupMapper.selectList(groupQueryWrapper);
    }

    /**
     * 考勤组管理 获取我管理的考勤组（树状结构展示）
     *
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> groupManagerList(GroupQueryDto groupQueryDto) {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupList(loginUserId, groupQueryDto);
//        List<AttendanceGroupVo> groupVoList = queryGroupListNew(loginUserId, groupQueryDto);
        /* 按照首字母排序*/
        sortByName(groupVoList);
//        List<AttendanceGroupVo> treeGroupList = treeGroupVo(groupVoList);

        return treeMyManagerGroupVo(groupVoList);
    }

    @Override
    public List<String> getEnableGroupIds(String groupId) {
        List<AttendanceGroupVo> enableGroup = getEnableGroup(groupId);
        List<String> collect = enableGroup.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
        collect.add(groupId);
        return collect;
    }

    private List<AttendanceGroupVo> getEnableGroup(String groupId) {
        List<AttendanceGroup> attendanceGroupVos = queryDropList();
        if (CollUtil.isEmpty(attendanceGroupVos)) {
            log.error("未查询到考勤组信息");
            return CollUtil.newArrayList();
        }
        AttendanceGroup attendanceGroup = attendanceGroupVos.stream().filter(group -> StringUtil.equals(group.getId(), groupId)).reduce((g1, g2) -> g1).orElse(null);
        if (attendanceGroup != null && Objects.equals(attendanceGroup.getAttendanceClassSetting(), 0)) {
            log.error("当前考勤组未开启班制配置");
            return CollUtil.newArrayList();
        }
        Map<String, List<AttendanceGroup>> groupIdToParent = attendanceGroupVos.stream().collect(Collectors.groupingBy(AttendanceGroup::getParentId));
        List<AttendanceGroupVo> groupVos = CollUtil.newArrayList();
        List<AttendanceGroup> orDefault = groupIdToParent.getOrDefault(groupId, CollUtil.newArrayList());
        if (CollUtil.isEmpty(orDefault)) {
            return CollUtil.newArrayList();
        }
        getEnableSingleGroup(orDefault, groupVos, groupIdToParent);
        return groupVos;
    }

    private void getEnableSingleGroup(List<AttendanceGroup> groups, List<AttendanceGroupVo> groupVos, Map<String, List<AttendanceGroup>> groupIdToParent) {
        groups.forEach(group -> {
            if (Objects.equals(group.getAttendanceClassSetting(), 1)) {
                return;
            }
            groupVos.add(BeanUtil.toBean(group, AttendanceGroupVo.class));
            List<AttendanceGroup> attendanceGroups = groupIdToParent.get(group.getId());
            if (CollUtil.isEmpty(attendanceGroups)) {
                return;
            }
            getEnableSingleGroup(attendanceGroups, groupVos, groupIdToParent);
        });
    }

    /**
     * 查询所有权限并赋予权限
     *
     * @param loginUserId 登录用户Id
     * @return List<AttendanceGroupVo>
     */
    public List<AttendanceGroupVo> queryGroupListSetPermission(String loginUserId, GroupQueryDto groupQueryDto) {
        if (Objects.isNull(groupQueryDto)) {
            groupQueryDto = new GroupQueryDto();
        }
        return queryGroupList(loginUserId, groupQueryDto);
    }

    /**
     * 查询所有权限并赋予权限
     *
     * @return List<AttendanceGroupVo>
     */
    public List<AttendanceGroupVo> queryGroupList(String loginUserId, GroupQueryDto groupQueryDto) {
        Boolean isAdmin = attendanceSuperAdminService.isSuperAdmin(loginUserId);
        /* 查询所有考勤组  V1.8.1 改为只查询本组权限 */
        List<AttendanceGroupVo> groupVoList = attendanceGroupMapper.getAllGroupList(groupQueryDto, null, null);
        if (isAdmin || userProvider.get().getIsAdministrator()) {

            /* 如果是超级管理员则全部赋予重命名和删除权限*/
            groupVoList.forEach(groupVo -> {
                groupVo.setIsAdmin(true);
                groupVo.setAddChild(true);
                groupVo.setRename(true);
                groupVo.setDelete(true);
                groupVo.setIsManager(true);
                groupVo.setScheduling(true);
                groupVo.setSecondedApproval(true);
                groupVo.setBalanceManagement(true);
                groupVo.setSecondedUser(true);
                //2024-04-22新增绑定组织
                groupVo.setBindingOrg(true);
                if (groupVo.getId().equals(GROUP_TOP_PARENT_ID)) {
                    groupVo.setDelete(false);
                }
            });
            return groupVoList;
        }
        if (CollectionUtil.isEmpty(groupVoList)) {
            return new ArrayList<>();
        }

        /* 找到我管理的考勤组所有的levelCode*/
        List<String> levelCodes = groupVoList.stream().map(AttendanceGroupVo::getLevelCode).collect(Collectors.toList());
        List<String> groupIdList = new ArrayList<>();
        levelCodes.forEach(levelCode -> {
            List<String> parentIdsByLevelCode = getParentIdsByLevelCode(levelCode, true);
            groupIdList.addAll(parentIdsByLevelCode);
        });

        if (CollectionUtil.isEmpty(groupIdList)) {
            return treeGroupVo(groupVoList);
        }

        Map<String, String> map = new HashMap<>();
        if (CollectionUtil.isNotEmpty(groupIdList)) {
            /* 查询有子级考勤组管理权限的考勤组信息列表*/
            List<CurUserPermissionVo> permissionVos = attendanceManagerPermissionMapper.queryInGroupIds(groupIdList, loginUserId);
            permissionVos.forEach(vo -> {
                map.put(vo.getGroupId(), vo.getAllPermissions());
            });
        }

        /* 获取我所属当前组权限*/
        List<AttendanceGroupVo> myGroupList = attendanceGroupMapper.getAllGroupList(groupQueryDto, loginUserId, PermissionTypeEnum.CUR.getCode());
        Map<String, String> myGroupPermissionMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(myGroupList)) {
            for (AttendanceGroupVo groupVo : myGroupList) {
                myGroupPermissionMap.put(groupVo.getId(), groupVo.getAllPermissions());
            }
        }

        /* 当前考勤组权限*/
        for (AttendanceGroupVo attendanceGroupVo : groupVoList) {
            String myPermissions = myGroupPermissionMap.get(attendanceGroupVo.getId());
            if (StrUtil.isBlank(myPermissions)) {
                attendanceGroupVo.setIsManager(false);
                continue;
            }
            attendanceGroupVo.setIsManager(true);
            attendanceGroupVo.setAddChild(myPermissions.contains(AttendancePermissionConstant.ADD_CHILD_GROUP));
            attendanceGroupVo.setRename(myPermissions.contains(AttendancePermissionConstant.RENAME));
            attendanceGroupVo.setDelete(myPermissions.contains(AttendancePermissionConstant.DELETE));
            attendanceGroupVo.setScheduling(myPermissions.contains(AttendancePermissionConstant.SCHEDULING));
            attendanceGroupVo.setBalanceManagement(myPermissions.contains(AttendancePermissionConstant.BALANCE_MANAGER));
            //2024-04-22新增绑定组织
            attendanceGroupVo.setBindingOrg(myPermissions.contains(AttendancePermissionConstant.BINDING_ORG));
            attendanceGroupVo.setSecondedApproval(myPermissions.contains(AttendancePermissionConstant.SECONDED_APPROVAL));
            attendanceGroupVo.setSecondedUser(myPermissions.contains(AttendancePermissionConstant.SECONDED_USER));
        }

        // 找到自己当前时间处于借调中的考勤组
        String userNowGroup = attendanceUserService.getUserNowGroup();
        if (null != userNowGroup) {
            // 查询用户所属的考勤组
            QueryWrapper<AttendanceGroupUser> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda()
                    .eq(AttendanceGroupUser::getUserGroupType, 1)
                    .isNull(AttendanceGroupUser::getRemoveTime)
                    .eq(AttendanceGroupUser::getUserId, userProvider.get().getUserId());
            AttendanceGroupUser groupUser = attendanceGroupUserMapper.selectOne(queryWrapper1);
            // 判断是否是该考勤组管理员
            if (!userNowGroup.equals(groupUser.getGroupId())) {
                // 当不是借调到组的管理员时 将借调到的考勤组赋值原组权限
                AttendanceGroupVo secondGroupVo = groupVoList.stream().filter(groupVo -> groupVo.getId().equals(userNowGroup)).findFirst().orElse(null);
                AttendanceGroupVo yuanGroup = groupVoList.stream().filter(groupVo -> groupVo.getId().equals(groupUser.getGroupId())).findFirst().orElse(null);
                if (yuanGroup != null) {
                    Objects.requireNonNull(secondGroupVo).setIsManager(yuanGroup.getIsManager());
                }
                Objects.requireNonNull(secondGroupVo).setAddChild(Objects.requireNonNull(yuanGroup).getAddChild());
                secondGroupVo.setRename(yuanGroup.getRename());
                secondGroupVo.setDelete(yuanGroup.getDelete());
                secondGroupVo.setScheduling(yuanGroup.getScheduling());
                secondGroupVo.setBalanceManagement(yuanGroup.getBalanceManagement());
                //2024-04-22新增绑定组织
                secondGroupVo.setBindingOrg(yuanGroup.getBindingOrg());
                secondGroupVo.setSecondedApproval(yuanGroup.getSecondedApproval());
                secondGroupVo.setSecondedUser(yuanGroup.getSecondedUser());
                // 原组是否具有子集考勤组权限
                String childPermissions = map.get(yuanGroup.getId());
                if (!StringUtil.isEmpty(childPermissions)) {
                    map.put(userNowGroup, childPermissions);
                }
            }
        }

        /* 子考勤组权限*/
        groupVoList.forEach(vo -> {
            String allPermissions = myGroupPermissionMap.get(vo.getId());
            if (StrUtil.isBlank(allPermissions)) {
                String levelCode = vo.getLevelCode();
                List<String> parentGroupIds = getParentIdsByLevelCode(levelCode, false);
                if (CollectionUtil.isNotEmpty(parentGroupIds)) {
                    for (String parent : parentGroupIds) {
                        String permissions = map.get(parent);
                        if (StrUtil.isNotBlank(permissions)) {
                            vo.setIsManager(true);
                            vo.setAddChild(permissions.contains(AttendancePermissionConstant.MANAGER));
                            vo.setRename(permissions.contains(AttendancePermissionConstant.MANAGER));
                            vo.setScheduling(permissions.contains(AttendancePermissionConstant.MANAGER));
                            vo.setDelete(permissions.contains(AttendancePermissionConstant.DELETE));
                            vo.setSecondedApproval(permissions.contains(AttendancePermissionConstant.SECONDED_APPROVAL));
                            //2024-04-22新增绑定组织
                            vo.setBindingOrg(permissions.contains(AttendancePermissionConstant.MANAGER));
                            vo.setSecondedUser(permissions.contains(AttendancePermissionConstant.MANAGER));
                            break;
                        }
                    }
                }
            }
        });
        return groupVoList;
    }


    public List<AttendanceGroupVo> queryGroupListSetPermissionNew(String loginUserId, GroupQueryDto groupQueryDto) {
        if (Objects.isNull(groupQueryDto)) {
            groupQueryDto = new GroupQueryDto();
        }
        return queryGroupListNew(loginUserId, groupQueryDto);
    }

    /**
     * v1.9 更换逻辑
     *
     * @param loginUserId   用户
     * @param groupQueryDto 参数
     */
    @Override
    public List<AttendanceGroupVo> queryGroupListNew(String loginUserId, GroupQueryDto groupQueryDto) {

        // 查看具有的权限列表
        FtbPermissionRoleIdentificationVO ftbPermissionRoleIdentificationVO = permissionsUtils.permissionIdentificationCollection();
        if (null == ftbPermissionRoleIdentificationVO) {
            return new ArrayList<>();
        }
        if (ftbPermissionRoleIdentificationVO.getIsSuperAdmin() == 1) {
            // 超级管理员
            List<AttendanceGroupVo> allGroupList = attendanceGroupMapper.getAllGroupList(groupQueryDto, null, null);
            allGroupList.forEach(v -> {
                v.setScheduling(true);
                v.setIsGray(false);
            });
            return allGroupList;
        }
        if (null == ftbPermissionRoleIdentificationVO.getPermissionIdentifications() || ftbPermissionRoleIdentificationVO.getPermissionIdentifications().isEmpty()) {
            // 没有页面权限
            return new ArrayList<>();
        }
        if (ftbPermissionRoleIdentificationVO.getPermissionIdentifications().contains(FuncCodingEnum.NEWTYPESETTING.getValue()) ||
                ftbPermissionRoleIdentificationVO.getPermissionIdentifications().contains(FuncCodingEnum.ATTENDANCESCHEDUL.getValue()) ||
                ftbPermissionRoleIdentificationVO.getPermissionIdentifications().contains(FuncCodingEnum.SETUPSCHEDUL.getValue()) ||
                ftbPermissionRoleIdentificationVO.getPermissionIdentifications().contains(FuncCodingEnum.WORKFORCEMANAGE.getValue())) {
            // 有排班权限
            // 获取用户指定模块的权限
            List<OrganizeGeneralDetailVO> organizeGeneralDetailVOS = ftbPermissionOrganizeService.authOrganizesByUserBound(null, null, false, false);
            /* 查询所有考勤组  V1.8.1 改为只查询本组权限 */
            if (CollectionUtil.isEmpty(organizeGeneralDetailVOS)) {
                // 当没有的时候，这个代表着没有权限
                return new ArrayList<>();
            }
            List<String> orgIds = organizeGeneralDetailVOS.stream().map(OrganizeGeneralDetailVO::getId).collect(Collectors.toList());
//            log.error("queryGroupListNew-- 用户具有的考勤组织权限 orgIds:{}", orgIds);
            // 有值返回 通过返回的组织Id，查看绑定的考勤组列表
            List<AttendanceGroupVo> attendanceGroupVos = attendanceGroupMapper.getGroupListByOrgId(groupQueryDto, orgIds);
            if (CollectionUtil.isEmpty(attendanceGroupVos)) {
                attendanceGroupVos = new ArrayList<>();
            }
            // 判断当前用户在当前时间是否处于借调
            // 找到自己当前时间处于借调中的考勤组    2.0 借调划归人事
//            String userNowGroup = attendanceUserService.getUserNowGroup();
//            if (StrUtil.isNotBlank(userNowGroup)) {
//                AttendanceGroup groupDetail = attendanceGroupMapper.getGroupDetail(userNowGroup);
//                if (null != groupDetail) {
//                    AttendanceGroupVo attendanceGroupVo = new AttendanceGroupVo();
//                    BeanUtils.copyProperties(groupDetail, attendanceGroupVo);
//                    attendanceGroupVos.add(attendanceGroupVo);
//                }
//            }
//            if (CollectionUtil.isEmpty(attendanceGroupVos)) {
//                return new ArrayList<>();
//            }
            // 通过考勤组的层级编码找到对应的所有考勤组
            List<String> levelCodes = attendanceGroupVos.stream().map(AttendanceGroupVo::getLevelCode).collect(Collectors.toList());
            List<String> groupIdList = new ArrayList<>();
            levelCodes.forEach(levelCode -> {
                List<String> parentIdsByLevelCode = getParentIdsByLevelCode(levelCode, true);
                groupIdList.addAll(parentIdsByLevelCode);
            });
            // 通过层级编码找到所有的考勤组
            List<String> list = groupIdList.stream().distinct().collect(Collectors.toList());
            if (!CollectionUtil.isEmpty(list)) {
                List<AttendanceGroupVo> groupVos = attendanceGroupMapper.getGroupListByIds(list);
                List<String> groupIds = attendanceGroupVos.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
                // 将包含groupIds的考勤组 isgary 设置为false
                groupVos.forEach(vo -> {
                    if (groupIds.contains(vo.getId())) {
                        vo.setScheduling(true);
                        vo.setIsGray(false);
                    }
                });
                return groupVos;
            }
        }
        return new ArrayList<>();
    }

    @Override
    public List<AttendanceOrgOrGroupVo> getOrgOrGroupList(String keyword) {
        List<OrganizeManagerFilterNodeVO> nodeVOList = ftbAuthorityApi.listOrganizeTreeFilterNode(List.of(OrganizeCategoryEnums.COMPANY,
                        OrganizeCategoryEnums.DEPARTMENT, OrganizeCategoryEnums.STORE, OrganizeCategoryEnums.TEAM),
                null, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE);
        // 获取所有考勤组
        List<AttendanceGroup> groupList = this.queryDropList();
        Map<String, AttendanceGroup> orgGroupMap = new HashMap<>();
        List<String> groupIds = CollUtil.isNotEmpty(groupList) ? groupList.stream().map(AttendanceGroup::getId).collect(Collectors.toList()) : new ArrayList<>();
        Map<String, AttendanceShiftSettingVo> shiftSettingMap = attendanceShiftSettingService.getEnableShiftSetting(groupIds, groupList);
        if (CollUtil.isNotEmpty(groupList)) {
            orgGroupMap = groupList.stream()
                    .filter(group -> StrUtil.isNotEmpty(group.getOrgId()))
                    .collect(Collectors.toMap(AttendanceGroup::getOrgId, a -> a, (k1, k2) -> k1));
        }
        // 将树形结构转换为扁平化列表
        List<AttendanceOrgOrGroupVo> result = new ArrayList<>();
        if (CollUtil.isNotEmpty(nodeVOList)) {
            flattenTreeWithGroups(nodeVOList, result, orgGroupMap, shiftSettingMap);
        }
        // 如果有关键字筛选
        if (StrUtil.isNotBlank(keyword)) {
            result = result.stream()
                    .filter(item -> StrUtil.containsIgnoreCase(item.getName(), keyword))
                    .collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 递归遍历树形结构并转换为扁平化列表，同时包含考勤组信息
     *
     * @param nodeList        树节点列表
     * @param result          结果列表
     * @param orgGroupMap     组织ID到考勤组列表的映射
     * @param shiftSettingMap 班次设置列表
     */
    private void flattenTreeWithGroups(List<OrganizeManagerFilterNodeVO> nodeList,
                                       List<AttendanceOrgOrGroupVo> result,
                                       Map<String, AttendanceGroup> orgGroupMap,
                                       Map<String, AttendanceShiftSettingVo> shiftSettingMap) {
        if (CollUtil.isEmpty(nodeList)) {
            return;
        }
        for (OrganizeManagerFilterNodeVO node : nodeList) {
            AttendanceGroup group = node.getNodeTypeEnum().equals(NodeTypeEnum.TEAM) ?
                    orgGroupMap.get(node.getPid()) : orgGroupMap.get(node.getId());
            AttendanceOrgOrGroupVo orgVo = new AttendanceOrgOrGroupVo();
            BeanUtils.copyProperties(node, orgVo);
            if (Objects.nonNull(group)) {
                orgVo.setGroupId(group.getId());
                orgVo.setIndependentRule(group.getBaseSetting());
                if (CollUtil.isNotEmpty(shiftSettingMap) && shiftSettingMap.containsKey(group.getId())) {
                    orgVo.setSystemType(Objects.nonNull(shiftSettingMap.get(group.getId())) ? shiftSettingMap.get(group.getId()).getSystemType() : null);
                }
            }
            result.add(orgVo);
            // 递归处理子节点
            if (CollUtil.isNotEmpty(node.getChildren())) {
                flattenTreeWithGroups(node.getChildren(), orgVo.getChildrenList(), orgGroupMap, shiftSettingMap);
            }
            orgVo.getChildren().clear();
        }
    }

    @Override
    @Transactional
    public Boolean setGroupCharge(AttendanceGroupChargeDto dto) {
        AttendanceGroup group = this.getById(dto.getGroupId());
        Assert.notNull(group, "考勤组不存在");
        group.setManagerId(dto.getManagerId());
        return this.updateById(group);
    }

    @Override
    public AttendanceGroupChargeVo getGroupChargeInfo(String groupId) {
        AttendanceGroup group = this.getById(groupId);
        Assert.notNull(group, "考勤组不存在");
        AttendanceGroupChargeVo groupChargeVo = AttendanceGroupChargeVo.builder()
                .managerId(StrUtil.isBlank(group.getManagerId()) ? null : group.getManagerId())
                .build();
        if (StrUtil.isNotBlank(group.getManagerId())) {
            ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getAllUserInfoBatch(
                    List.of(group.getManagerId()), UserProvider.getUser().getTenantId());
            if (actionResult.getCode() == 200 && CollUtil.isNotEmpty(actionResult.getData())) {
                actionResult.getData().stream().findFirst().ifPresent(user ->
                        groupChargeVo.setManagerName(user.getUserName()));
            }
        }
        return groupChargeVo;
    }

    @Override
    public void removeManager(String groupId, List<String> removeUserIds) {
        LambdaUpdateWrapper<AttendanceGroup> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AttendanceGroup::getId, groupId);
        updateWrapper.isNotNull(AttendanceGroup::getManagerId);
        updateWrapper.in(AttendanceGroup::getManagerId, removeUserIds);
        updateWrapper.set(AttendanceGroup::getManagerId, null);
        this.update(updateWrapper);
    }


    /**
     * 根据levelCode获取考勤组父id
     *
     * @return List<String>
     */
    private List<String> getParentIdsByLevelCode(String levelCode, Boolean hasCur) {
        if (StrUtil.isBlank(levelCode)) {
            return new ArrayList<>();
        }
        String[] split = levelCode.split("#");
        List<String> tempList = new ArrayList<>();
        CollectionUtil.addAll(tempList, split);
        if (!hasCur) {
            tempList.remove(0);
        }
        return new ArrayList<>(tempList);
    }

    /**
     * 借调开始
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void secondedStart(AttendanceSecondedDto attendanceSecondedDto) throws HandleException {

        List<String> userIds = attendanceSecondedDto.getUserIds();
        if (CollectionUtil.isEmpty(userIds)) {
            throw new HandleException("请选择借调人员");
        }

        /* 校验借调组是否已解散*/
        AttendanceGroup group = attendanceGroupMapper.selectById(attendanceSecondedDto.getGroupId());
        if (group.getDeleteMark() == 1) {
            throw new HandleException("考勤组或借调组已不存在!");
        }
        /* 校验被借调考勤组是否已解散*/
        AttendanceGroup selfGroup = attendanceGroupMapper.selectById(attendanceSecondedDto.getSelfGroupId());
        if (selfGroup.getDeleteMark() == 1) {
            throw new HandleException("考勤组或借调组已不存在!");
        }

        /* 校验借调过程中借调人员是否离开借调考勤组*/
        QueryWrapper<AttendanceGroupUser> groupUserQueryWrapper = new QueryWrapper<>();
        groupUserQueryWrapper.lambda()
                .eq(AttendanceGroupUser::getGroupId, attendanceSecondedDto.getSelfGroupId())
                .eq(AttendanceGroupUser::getType, GroupUserTypeEnum.CUR.getCode());
        List<AttendanceGroupUser> groupUserList = attendanceGroupUserMapper.selectList(groupUserQueryWrapper);

        if (CollectionUtil.isEmpty(groupUserList)) {
            throw new HandleException("被借调考勤组下无成员或已被全部移除该考勤组!");
        }
        List<String> dbUserIds = groupUserList.stream().map(AttendanceGroupUser::getUserId).collect(Collectors.toList());

        List<String> differenceUserIds = userIds.stream().filter(userId -> {
            return !dbUserIds.contains(userId);
        }).collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(differenceUserIds)) {
            String join = CollectionUtil.join(differenceUserIds, ",");
            throw new HandleException(join + "已离开被借调考勤组!");
        }

        /* 被借调考勤组信息*/
        groupUserInfoSave(attendanceSecondedDto, GroupUserTypeEnum.CUR.getCode());
        /* 借调考勤组信息*/
        groupUserInfoSave(attendanceSecondedDto, GroupUserTypeEnum.BORROW.getCode());
        userIds.forEach(userId -> attendanceClockInService.generateRepairNumForUser(attendanceSecondedDto.getGroupId(), userId, 2));


    }

    /**
     * 获取默认考勤组
     *
     * @return AttendanceGroup
     */
    @Override
    public AttendanceGroupVo getDefaultGroup() {
        String loginUserId = UserProvider.getLoginUserId();
        Object defaultGroup = redisTemplate.opsForValue().get(RedisConstant.CACHE_GROUP + loginUserId);

        AttendanceGroupVo group = JsonUtil.getJsonToBean(defaultGroup, AttendanceGroupVo.class);
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        List<AttendanceGroupVo> managerGroupList = groupVoList.stream().filter(vo -> !Objects.equals(vo.getDeleteMark(), 1)).filter(AttendanceGroupVo::getIsManager).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(managerGroupList)) {
            return null;
        }
        List<String> managerGroupIds = managerGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
        if (group != null && MybatisUtil.findByFiled(attendanceGroupMapper, AttendanceGroup::getId, group.getId(), true) != null && managerGroupIds.contains(group.getId())) {
            return group;
        }

        sortByName(groupVoList);
        AttendanceGroupVo attendanceGroupVo = managerGroupList.get(0);
        redisTemplate.opsForValue().set(RedisConstant.CACHE_GROUP + loginUserId, attendanceGroupVo);
        return attendanceGroupVo;
    }

    /**
     * 切换考勤组
     * 498140478206886917
     */
    @Override
    public void handoffGroup(String groupId) {
        String loginUserId = UserProvider.getLoginUserId();
        AttendanceGroup group = MybatisUtil.findByFiled(attendanceGroupMapper, AttendanceGroup::getId, groupId, true);
        redisTemplate.opsForValue().set(RedisConstant.CACHE_GROUP + loginUserId, group);
    }

    @Override
    public AttendanceGroupStatusDto groupSettingStatus(String groupId, Boolean aFalse) {
        AttendanceGroup attendanceGroup = attendanceGroupMapper.selectById(groupId);
        if (Objects.equals(attendanceGroup.getAttendancePointsSetting(), 0)) {
            AttendanceGroup attendanceGroup2 = getEnableLocationSetting(groupId);
            if (Objects.nonNull(attendanceGroup2)) {
                if (!aFalse) {
                    attendanceGroup.setGpsEnable(attendanceGroup2.getGpsEnable());
                    attendanceGroup.setWifiEnable(attendanceGroup2.getWifiEnable());
                    attendanceGroup.setMachineEnable(attendanceGroup2.getMachineEnable());
                }
            } else {
                attendanceGroup.setGpsEnable(0);
                attendanceGroup.setWifiEnable(0);
                attendanceGroup.setMachineEnable(0);
            }
        }
        AttendanceGroupStatusDto result = BeanUtil.toBean(attendanceGroup, AttendanceGroupStatusDto.class);
        result.setIsRootGroup(attendanceGroup.getId().equals(GROUP_TOP_PARENT_ID));
        result.setGroupId(attendanceGroup.getId());
        return result;
    }

    private AttendanceGroup getEnableLocationSetting(String groupId) {
        List<AttendanceGroup> attendanceGroupVos = queryDropList();
        if (CollUtil.isEmpty(attendanceGroupVos)) {
            log.error("未查询到考勤组信息");
            return null;
        }
        Map<String, String> groupIdToParent = attendanceGroupVos.stream().collect(Collectors.toMap(AttendanceGroup::getId, groupVo -> StringUtil.isBlank(groupVo.getParentId()) ? "-1" : groupVo.getParentId()));
        Map<String, AttendanceGroup> collect = attendanceGroupVos.stream().filter(group -> group.getAttendancePointsSetting() == 1).collect(Collectors.toMap(AttendanceGroup::getId, group -> group));
        return findNextBaseSetting(collect, groupIdToParent, groupId);
    }

    /**
     * 获取考勤组下个考勤组配置
     */
    private AttendanceGroup findNextBaseSetting(Map<String, AttendanceGroup> collect, Map<String, String> groupIdToParent, String groupId) {
        if (StringUtil.isBlank(groupId)) {
            return null;
        }
        if (!collect.containsKey(groupId)) {
            return findNextBaseSetting(collect, groupIdToParent, groupIdToParent.get(groupId));
        }
        return collect.get(groupId);
    }

    private void groupUserInfoSave(AttendanceSecondedDto attendanceSecondedDto, Integer groupType) throws HandleException {
        for (String userId : attendanceSecondedDto.getUserIds()) {
            /* 验证用户是否有被其它组借调*/
            QueryWrapper<AttendanceGroupUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(AttendanceGroupUser::getUserId, userId)
                    .eq(AttendanceGroupUser::getType, GroupUserTypeEnum.CUR.getCode()).eq(AttendanceGroupUser::getDeleteMark, 0)
                    .isNotNull(AttendanceGroupUser::getTimeJson);
            AttendanceGroupUser groupUser = attendanceGroupUserMapper.selectOne(queryWrapper);
            if (groupUser != null) {
                /* 验证日期*/
                String timeJson = groupUser.getTimeJson();
                List<String> timeJsonList = JsonUtil.getJsonToList(timeJson, String.class);
                if (CollectionUtil.isNotEmpty(timeJsonList) && GroupUserTypeEnum.CUR.getCode().equals(groupType)) {
                    /* 日期校验*/
                    this.checkSecondDate(timeJsonList, attendanceSecondedDto.getStartTime(), attendanceSecondedDto.getEndTime(), attendanceSecondedDto.getDepartureTime(), attendanceSecondedDto.getBackTime(), userId);
                }
            }

            /* 先查询该组下的该用户*/
            queryWrapper.clear();
            queryWrapper
                    .lambda()
                    .eq(AttendanceGroupUser::getType, GroupUserTypeEnum.CUR.getCode())
                    .eq(AttendanceGroupUser::getUserId, userId)
                    .eq(AttendanceGroupUser::getDeleteMark, 0);
            AttendanceGroupUser dbGroupUser = attendanceGroupUserMapper.selectOne(queryWrapper);
            if (GroupUserTypeEnum.CUR.getCode().equals(groupType)) {
                String dbGroupUserTimeJson = dbGroupUser.getTimeJson();
                dbGroupUser.setGroupId(attendanceSecondedDto.getSelfGroupId());
                SecondmentDateVo secondmentDateVo = SecondmentDateVo.builder()
                        .approvalId(attendanceSecondedDto.getId())
                        .startTime(attendanceSecondedDto.getDepartureTime())
                        .endTime(attendanceSecondedDto.getBackTime()).build();

                List<SecondmentDateVo> dateVoList = JSON.parseArray(dbGroupUserTimeJson, SecondmentDateVo.class);
                if (CollectionUtil.isEmpty(dateVoList)) {
                    dateVoList = new ArrayList<>();
                }
                dateVoList.add(secondmentDateVo);
                String timeJson = JsonUtil.getObjectToString(dataToTimeJson(dateVoList));
                dbGroupUser.setTimeJson(timeJson);
                dbGroupUser.setGroupId(attendanceSecondedDto.getSelfGroupId());
                dbGroupUser.setRemoveTime(null);
                dbGroupUser.setDeleteMark(0);
                attendanceGroupUserMapper.updateById(dbGroupUser);
//                return;
            } else {
                /* 被借调考勤组*/
                queryWrapper.clear();
                queryWrapper
                        .lambda()
//                        .eq(AttendanceGroupUser::getType, GroupUserTypeEnum.BORROW.getCode())
                        .ne(AttendanceGroupUser::getType, GroupUserTypeEnum.CUR.getCode())
                        .eq(AttendanceGroupUser::getGroupId, attendanceSecondedDto.getGroupId())
                        .eq(AttendanceGroupUser::getUserId, userId).eq(AttendanceGroupUser::getDeleteMark, 0);
                AttendanceGroupUser borrowGroupUser = attendanceGroupUserMapper.selectOne(queryWrapper);
                if (borrowGroupUser == null) {
                    /* 未找到考勤组成员*/
                    borrowGroupUser = new AttendanceGroupUser();
                    borrowGroupUser.setId(RandomUtil.uuId());
                    borrowGroupUser.setGroupId(attendanceSecondedDto.getGroupId());
                    borrowGroupUser.setUserId(userId);
                    borrowGroupUser.setType(groupType);
                    borrowGroupUser.setUserGroupType(groupType);
                    borrowGroupUser.setCreatorTime(new Date());
                    String loginUserId = UserProvider.getLoginUserId();
                    borrowGroupUser.setCreatorUserId(StringUtil.isEmpty(loginUserId) ? "admin" : loginUserId);
                    borrowGroupUser.setDeleteMark(0);
                    List<SecondmentDateVo> dateVoList = new ArrayList<>();
                    SecondmentDateVo secondmentDateVo = SecondmentDateVo.builder()
                            .approvalId(attendanceSecondedDto.getId())
                            .startTime(attendanceSecondedDto.getStartTime())
                            .endTime(attendanceSecondedDto.getEndTime()).build();
                    dateVoList.add(secondmentDateVo);
                    String timeJson = JsonUtil.getObjectToString(dataToTimeJson(dateVoList));
                    borrowGroupUser.setTimeJson(timeJson);
                    attendanceGroupUserMapper.insert(borrowGroupUser);
                    continue;
//                    return;
                }

                List<SecondmentDateVo> dateVoList = JSON.parseArray(borrowGroupUser.getTimeJson(), SecondmentDateVo.class);
                if (CollectionUtil.isEmpty(dateVoList)) {
                    dateVoList = new ArrayList<>();
                }
                SecondmentDateVo secondmentDateVo = SecondmentDateVo.builder()
                        .approvalId(attendanceSecondedDto.getId())
                        .startTime(attendanceSecondedDto.getStartTime())
                        .endTime(attendanceSecondedDto.getEndTime()).build();

                dateVoList.add(secondmentDateVo);
                String timeJson = JsonUtil.getObjectToString(dataToTimeJson(dateVoList));
                borrowGroupUser.setTimeJson(timeJson);
                borrowGroupUser.setType(groupType);
                borrowGroupUser.setUserGroupType(groupType);
                borrowGroupUser.setRemoveTime(null);
                borrowGroupUser.setDeleteMark(0);
                attendanceGroupUserMapper.updateById(borrowGroupUser);
            }
        }
    }

    /**
     * 日期转json
     */
    private List<Map<String, String>> dataToTimeJson(List<SecondmentDateVo> secondmentDateVos) {
        List<Map<String, String>> objects = CollUtil.newArrayList();
        String format = "yyyy-MM-dd HH:mm:ss";
        for (SecondmentDateVo secondmentDateVo : secondmentDateVos) {
            Date startTime = secondmentDateVo.getStartTime();
            Date endTime = secondmentDateVo.getEndTime();
            Map<String, String> map = new HashMap<>();
            map.put("approvalId", secondmentDateVo.getApprovalId());
            map.put("startTime", cn.hutool.core.date.DateUtil.format(startTime, format));
            map.put("endTime", cn.hutool.core.date.DateUtil.format(endTime, format));
            objects.add(map);
        }
        return objects;
    }

    /**
     * 查询是否有排班权限的考勤组列表
     *
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> schedulingGroupList() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);
        sortByName(groupVoList);
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || groupVo.getScheduling();
        }).collect(Collectors.toList());
        sortByName(schedulingGroupList);
        return treeMyManagerGroupVo(schedulingGroupList);
    }

    @Override
    public List<AttendanceGroupVo> schedulingGroupListByNotFixed() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);

        sortByName(groupVoList);
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || groupVo.getScheduling();
        }).collect(Collectors.toList());
        List<String> groupIds = schedulingGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
        Map<String, AttendanceShiftSettingVo> enableShiftSetting = attendanceShiftSettingService.getEnableShiftSetting(groupIds, queryDropList());
        schedulingGroupList = schedulingGroupList.stream().filter(groupVo -> {
            AttendanceShiftSettingVo attendanceShiftSettingVo = enableShiftSetting.get(groupVo.getId());
            if (Objects.isNull(attendanceShiftSettingVo)) {
                return Boolean.FALSE;
            }
            return Objects.equals(attendanceShiftSettingVo.getSystemType(), 2);
        }).collect(Collectors.toList());
        sortByName(schedulingGroupList);
        return treeMyManagerGroupVo(schedulingGroupList);
    }

    /**
     * 获取有余额管理权限的考勤组列表
     *
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> balanceManagement() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);
        sortByName(groupVoList);
        /* 筛选出有余额管理权限的考勤组*/
        List<AttendanceGroupVo> balanceManagementGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || groupVo.getBalanceManagement();
        }).collect(Collectors.toList());
        sortByName(balanceManagementGroupList);
        return treeMyManagerGroupVo(balanceManagementGroupList);
    }

    /**
     * 查询我有借调权限的考勤组列表
     */
    @Override
    public List<AttendanceGroupVo> secondedApprovalGroupList() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);
        sortByName(groupVoList);
        /* 筛选出有余额管理权限的考勤组*/
        return groupVoList.stream().filter(AttendanceGroupVo::getSecondedUser).collect(Collectors.toList());
    }

    @Override
    public List<AttendanceGroupVo> viewApprovalGroupList(String name) {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, null);
        groupVoList = groupVoList.stream().filter(AttendanceGroupVo::getIsManager).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        Pattern pattern = Pattern.compile(".*" + name + ".*", Pattern.CASE_INSENSITIVE);
        groupVoList = groupVoList.stream()
                .filter(x -> pattern.matcher(x.getGroupName()).matches())
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        sortByName(groupVoList);
        return groupVoList;
    }


    @Override
    public List<AttendanceGroupVo> viewApprovalGroupListNew(String name) {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);
        groupVoList = groupVoList.stream().filter(vo -> !vo.getIsGray()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        Pattern pattern = Pattern.compile(".*" + name + ".*", Pattern.CASE_INSENSITIVE);
        groupVoList = groupVoList.stream()
                .filter(x -> pattern.matcher(x.getGroupName()).matches())
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        sortByName(groupVoList);
        return groupVoList;
    }

    /**
     * 获取用户以及用户所管理的考勤组
     *
     * @return Map<String, List < String>>
     */
    @Override
    public Map<String, List<String>> userManagerGroupInfo() {
        //查询所有考勤组当前组管理员
        QueryWrapper<AttendanceManagerPermission> managerQuery = new QueryWrapper<>();
        managerQuery.lambda()
                .eq(AttendanceManagerPermission::getType, 1);
        List<AttendanceManagerPermission> curManagerList = attendanceManagerPermissionMapper.selectList(managerQuery);
        if (CollectionUtil.isEmpty(curManagerList)) {
            return new HashMap<>();
        }

        QueryWrapper<PermissionDict> permissionQuery = new QueryWrapper<>();
        permissionQuery.lambda()
                .eq(PermissionDict::getModuleType, 2)
                .eq(PermissionDict::getName, "查看");

        PermissionDict viewPermission = permissionDictMapper.selectOne(permissionQuery);

        //子考勤组权限
        managerQuery.clear();
        managerQuery.lambda()
                .eq(AttendanceManagerPermission::getType, 2)
                .eq(AttendanceManagerPermission::getPermissionId, viewPermission.getId());
        List<AttendanceManagerPermission> childManagerList = attendanceManagerPermissionMapper.selectList(managerQuery);
        Map<String, List<AttendanceManagerPermission>> childGroupMap = childManagerList.stream().collect(Collectors.groupingBy(AttendanceManagerPermission::getUserId));

        //查询考勤组
        QueryWrapper<AttendanceGroup> groupQuery = new QueryWrapper<>();
        groupQuery.lambda()
                .eq(AttendanceGroup::getDeleteMark, 0);
        List<AttendanceGroup> groupList = attendanceGroupMapper.selectList(groupQuery);
        Map<String, AttendanceGroup> groupMap = groupList.stream().collect(Collectors.toMap(AttendanceGroup::getId, group -> group));

        Map<String, List<String>> resultMap = new HashMap<>();
        Map<String, List<AttendanceManagerPermission>> curManagerMap = curManagerList.stream().collect(Collectors.groupingBy(AttendanceManagerPermission::getUserId));
        curManagerMap.forEach((userId, attendanceManagerPermissionList) -> {
            Set<String> groupIdSet = attendanceManagerPermissionList.stream().map(AttendanceManagerPermission::getGroupId).collect(Collectors.toSet());
            for (AttendanceManagerPermission permission : attendanceManagerPermissionList) {
                //在查看是否有子权限
                List<AttendanceManagerPermission> childManagerInfo = childGroupMap.get(permission.getUserId());
                if (CollectionUtil.isEmpty(childManagerInfo)) {
                    resultMap.put(permission.getUserId(), ListUtil.toList(groupIdSet));
                    continue;
                }
                List<AttendanceGroup> childGroupList = groupList.stream().filter(group -> {
                    return group.getLevelCode().contains(permission.getGroupId());
                }).collect(Collectors.toList());
                Set<String> childGroupIds = childGroupList.stream().map(AttendanceGroup::getId).collect(Collectors.toSet());
                groupIdSet.addAll(childGroupIds);
                resultMap.put(permission.getUserId(), ListUtil.toList(groupIdSet));
            }

        });

        return resultMap;
    }

    @Override
    public List<AttendanceGroup> getGroupListByOrgIds(List<String> orgIds) {
        return this.lambdaQuery().in(AttendanceGroup::getOrgId, orgIds)
                .isNotNull(AttendanceGroup::getOrgId)
                .eq(AttendanceGroup::getDeleteMark, 0)
                .orderByDesc(AttendanceGroup::getCreatorTime)
                .list();
    }

    @Override
    public boolean appointPermission(AppointPermission permissionCode) {
        UserInfo userInfo = userProvider.get();
        Boolean isAdmin = attendanceSuperAdminService.isSuperAdmin(userInfo.getUserId());
        if (isAdmin || userInfo.getIsAdministrator()) {
            // 系统超管、考勤组超管默认有所有权限
            return true;
        }
        // 查询用户在当前考勤组是否是否有指定权限
        Integer count = attendanceGroupMapper.appointPermissionByGroupId(userInfo.getUserId(), permissionCode.getGroupId(), permissionCode.getPermissionCode(), PermissionTypeEnum.CUR.getCode());
        if (count > 0) {
            return true;
        }
        // 没有，校验当前考勤组的父级是否拥有子组管理权限
        AttendanceGroup group = attendanceGroupMapper.selectById(permissionCode.getGroupId());
        String[] parentGroupIdArr = group.getLevelCode().split("#");
        List<String> groupIds = Arrays.stream(parentGroupIdArr).collect(Collectors.toList());
        boolean b = false;
        for (String groupId : groupIds) {
            Integer num = attendanceGroupMapper.appointPermissionByGroupId(userInfo.getUserId(), groupId, "manager", PermissionTypeEnum.CHILD.getCode());
            if (num > 0) {
                b = true;
                break;
            }
        }
        return b;
    }

    @Override
    public AttendanceGroup getGroupSetting(String groupId) {
        return attendanceGroupMapper.selectById(groupId);
    }

    @Override
    public List<AttendanceGroupVo> groupMyManagerList(GroupQueryDto groupQueryDto) {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListNew(loginUserId, groupQueryDto);
        // 查询所有绑定了考勤机的考勤组
        String groupBindIds = attendanceMachineManageMapper.selectGroupBindMachine();
        Set<String> set = new HashSet<>();
        if (null != groupBindIds && !groupBindIds.isEmpty()) {
            String[] split = groupBindIds.split(",");
            Collections.addAll(set, split);
        }
        groupVoList.forEach(v -> {
            if (set.contains(v.getId())) {
                v.setBindingMachine(true);
            }
        });
        // 按照首字母排序
        sortByName(groupVoList);
        return treeMyManagerGroupVo(groupVoList);
    }

    @Override
    public List<AttendanceGroupVo> schedulingGroupListByNotFixedNew() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);

        sortByName(groupVoList);
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || !groupVo.getIsGray();
        }).collect(Collectors.toList());
        List<String> groupIds = schedulingGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
        Map<String, AttendanceShiftSettingVo> enableShiftSetting = attendanceShiftSettingService.getEnableShiftSetting(groupIds, queryDropList());
        schedulingGroupList = schedulingGroupList.stream().filter(groupVo -> {
            AttendanceShiftSettingVo attendanceShiftSettingVo = enableShiftSetting.get(groupVo.getId());
            if (Objects.isNull(attendanceShiftSettingVo)) {
                return Boolean.FALSE;
            }
            return Objects.equals(attendanceShiftSettingVo.getSystemType(), 2);
        }).collect(Collectors.toList());
        sortByName(schedulingGroupList);
        return treeMyManagerGroupVo(schedulingGroupList);
    }

    @Override
    public List<AttendanceGroupVo> handoffGroupTreeListNew() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, new GroupQueryDto());
        List<AttendanceGroupVo> managerGroupList = groupVoList.stream().filter(group -> {
            return !group.getIsGray() || group.getId().equals(GROUP_TOP_PARENT_ID);
        }).collect(Collectors.toList());
        return treeMyManagerGroupVo(managerGroupList);
    }

    @Override
    public AttendanceGroupVo getDefaultGroupNew() {
        String loginUserId = UserProvider.getLoginUserId();
        Object defaultGroup = redisTemplate.opsForValue().get(RedisConstant.CACHE_GROUP + loginUserId);

        AttendanceGroupVo group = JsonUtil.getJsonToBean(defaultGroup, AttendanceGroupVo.class);
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);
        if (CollectionUtil.isEmpty(groupVoList)) {
            return null;
        }
        List<AttendanceGroupVo> managerGroupList = groupVoList.stream().filter(vo -> !Objects.equals(vo.getDeleteMark(), 1)).filter(vo -> !vo.getIsGray()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(managerGroupList)) {
            return null;
        }
        List<String> managerGroupIds = managerGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
        if (group != null && MybatisUtil.findByFiled(attendanceGroupMapper, AttendanceGroup::getId, group.getId(), true) != null && managerGroupIds.contains(group.getId())) {
            return group;
        }

        sortByName(groupVoList);
        AttendanceGroupVo attendanceGroupVo = managerGroupList.get(0);
        redisTemplate.opsForValue().set(RedisConstant.CACHE_GROUP + loginUserId, attendanceGroupVo);
        return attendanceGroupVo;
    }

    @Override
    public List<AttendanceGroupVo> schedulingGroupListNew() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);
//        sortByName(groupVoList);
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || !groupVo.getIsGray();
        }).collect(Collectors.toList());
        sortByName(schedulingGroupList);
        return treeMyManagerGroupVo(schedulingGroupList);
    }

    @Override
    public List<AttendanceGroupVo> balanceManagementNew() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);
//        sortByName(groupVoList);
        /* 筛选出有余额管理权限的考勤组*/
        List<AttendanceGroupVo> balanceManagementGroupList = groupVoList.stream().filter(groupVo -> {
            return groupVo.getId().equals(GROUP_TOP_PARENT_ID) || !groupVo.getIsGray();
        }).collect(Collectors.toList());
        sortByName(balanceManagementGroupList);
        return treeMyManagerGroupVo(balanceManagementGroupList);
    }

    @Override
    public List<AttendanceGroupVo> secondedApprovalGroupListNew() {
//        String loginUserId = UserProvider.getLoginUserId();
        // 2.0 修改为不看权限
        List<AttendanceGroupVo> groupVoList = attendanceGroupMapper.getAllGroupList(new GroupQueryDto(), null, null);
        groupVoList.forEach(v -> {
            v.setScheduling(true);
            v.setIsGray(false);
        });
//        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermissionNew(loginUserId, null);
        sortByName(groupVoList);
        /* 筛选出有余额管理权限的考勤组*/
        return groupVoList.stream().filter(groupVo -> {
            return !groupVo.getIsGray();
        }).collect(Collectors.toList());
    }


    @Override
    public List<String> getGroupIdsByManagePermission(String userId, boolean b) {
//        List<AttendanceGroupVo> groupVoList = queryGroupList(userId, new GroupQueryDto());
        // v1.9 切换权限判断逻辑
        List<AttendanceGroupVo> groupVoList = queryGroupListNew(userId, new GroupQueryDto());
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(AttendanceGroupVo::getScheduling).collect(Collectors.toList());
        List<String> groupIds = schedulingGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
//        if (b) {
//            // 去掉固定班考勤组  todo 2.0 没有固定排班说法，后续还要改
//            Map<String, AttendanceShiftSettingVo> enableShiftSetting = attendanceShiftSettingService.getEnableShiftSetting(groupIds, queryDropList());
//            schedulingGroupList = schedulingGroupList.stream().filter(groupVo -> {
//                AttendanceShiftSettingVo attendanceShiftSettingVo = enableShiftSetting.get(groupVo.getId());
//                if (Objects.isNull(attendanceShiftSettingVo)) {
//                    return Boolean.FALSE;
//                }
//                return Objects.equals(attendanceShiftSettingVo.getSystemType(), 2);
//            }).collect(Collectors.toList());
//            groupIds = schedulingGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
//        }
        return groupIds;
    }

    @Override
    public boolean checkScheduling() {
        List<AttendanceGroupVo> groupVoList = queryGroupList(userProvider.get().getUserId(), new GroupQueryDto());
        /* 筛选出有排班权限的考勤组*/
        List<AttendanceGroupVo> schedulingGroupList = groupVoList.stream().filter(AttendanceGroupVo::getScheduling).collect(Collectors.toList());
        return !schedulingGroupList.isEmpty();
    }

    @Override
    public List<AttendanceGroupVo> getPermissionsGroupList(String positionModuleName) {
        List<OrganizeGeneralDetailVO> organizeGeneralDetailVOS = ftbPermissionOrganizeService.authOrganizesByUserBound(List.of(OrganizeCategoryEnums.COMPANY, OrganizeCategoryEnums.DEPARTMENT),
                null, false, false);
        if (CollUtil.isEmpty(organizeGeneralDetailVOS) || CollUtil.isEmpty(organizeGeneralDetailVOS.stream()
                .map(OrganizeGeneralDetailVO::getId).distinct().collect(Collectors.toList()))) {
            return List.of();
        }
        List<String> organizeIds = organizeGeneralDetailVOS.stream().map(OrganizeGeneralDetailVO::getId).distinct().collect(Collectors.toList());
        //获取组织下所有考勤组
        GroupQueryDto groupQueryDto = new GroupQueryDto();
        groupQueryDto.setType(0);
        groupQueryDto.setOrgIds(organizeIds);
        return queryGroupList(UserProvider.getLoginUserId(), groupQueryDto);
    }


    /**
     * 获取切换考勤组列表（树结构）
     *
     * @return List<AttendanceGroupVo>
     */
    @Override
    public List<AttendanceGroupVo> handoffGroupTreeList() {
        String loginUserId = UserProvider.getLoginUserId();
        List<AttendanceGroupVo> groupVoList = queryGroupListSetPermission(loginUserId, new GroupQueryDto());
        List<AttendanceGroupVo> managerGroupList = groupVoList.stream().filter(group -> {
            return group.getIsManager() || group.getId().equals(GROUP_TOP_PARENT_ID);
        }).collect(Collectors.toList());
        return treeMyManagerGroupVo(managerGroupList);
    }

    @Override
    public List<AttendanceGroupVo> groupListByOrgId(String orgId) {
        List<AttendanceGroupVo> groupVos = attendanceGroupMapper.groupListByOrgId(orgId);
        List<String> groupIds = CollUtil.newArrayList();
        groupVos.forEach(groupVo -> {
            if (StringUtil.isEmpty(groupVo.getLevelCode())) {
                return;
            }
            groupIds.addAll(Arrays.stream(groupVo.getLevelCode().split("#")).collect(Collectors.toList()));
        });
        if (CollUtil.isEmpty(groupIds)) {
            return groupVos;
        }
        List<AttendanceGroup> list = lambdaQuery().in(AttendanceGroup::getId, groupIds).eq(AttendanceGroup::getDeleteMark, Boolean.FALSE).list();
        if (CollUtil.isEmpty(list)) {
            return groupVos;
        }
        groupVos.forEach(groupVo -> {
            if (StringUtil.isEmpty(groupVo.getLevelCode())) {
                return;
            }
            List<String> ids = Arrays.stream(groupVo.getLevelCode().split("#")).collect(Collectors.toList());
            String detailName = list.stream().filter(group -> ids.contains(group.getId()))
                    .sorted(Comparator.comparing(AttendanceGroup::getCreatorTime))
                    .map(AttendanceGroup::getGroupName)
                    .reduce((r1, r2) -> r1 + "/" + r2)
                    .orElse("");
            groupVo.setDetailName(detailName);
        });
        return groupVos;
    }

    @Override
    public AttendanceGroupVo getGroupBindingOrg(String groupId, String workGroupId) {
        AttendanceGroupVo attendanceGroupVo = attendanceGroupMapper.getGroupBindingOrg(groupId);
        if (null == attendanceGroupVo) {
            return attendanceGroupVo;
        }
        // 调用Flynn接口 入参 组织Id集合 返回 List<model> model-> id,当前组织名称，拼接好的包含父级组织的名称
        if (null != attendanceGroupVo.getOrgId()) {
            List<String> list = new ArrayList<>();
            list.add(attendanceGroupVo.getOrgId());
            ActionResult<List<OrganizeGeneralDetailVO>> listActionResult = v2OrganizeApi.organizesByOrganizeIds(list);
            if (200 == listActionResult.getCode() && null != listActionResult.getData()) {
                listActionResult.getData().stream().filter(t -> t.getId().equals(attendanceGroupVo.getOrgId())).findFirst().ifPresent(organizeGeneralDetailVO -> attendanceGroupVo.setBindingOrgName(organizeGeneralDetailVO.getOrganizeTreeName()));
            }
        }
        attendanceGroupVo.setDetailName(recursionParent(attendanceGroupVo.getLevelCode()));
        //查询人员数
        List<UserBoundVO> userBoundVO = attendanceUserService.getUserBoundVO(groupId, workGroupId);
        attendanceGroupVo.setUserCount(Objects.isNull(userBoundVO) ? 0 : userBoundVO.stream().filter(vo -> !StringUtil.equals(vo.getUserName(), "管理员")).count());
        return attendanceGroupVo;
    }

    @Override
    public AttendanceGroupVo getGroupBindingOrgForLine(String groupId, String workGroupId) {
        AttendanceGroupVo attendanceGroupVo = attendanceGroupMapper.getGroupBindingOrg(groupId);
        if (null == attendanceGroupVo) {
            return attendanceGroupVo;
        }
        attendanceGroupVo.setDetailName(recursionParent(attendanceGroupVo.getLevelCode()));
        attendanceGroupVo.setUserCount(0);
        // 调用Flynn接口 入参 组织Id集合 返回 List<model> model-> id,当前组织名称，拼接好的包含父级组织的名称
        if (null != attendanceGroupVo.getOrgId()) {
            List<String> list = new ArrayList<>();
            list.add(attendanceGroupVo.getOrgId());
            ActionResult<List<OrganizeGeneralDetailVO>> listActionResult = v2OrganizeApi.organizesByOrganizeIds(list);
            if (200 == listActionResult.getCode() && null != listActionResult.getData()) {
                listActionResult.getData().stream().filter(t -> t.getId().equals(attendanceGroupVo.getOrgId())).findFirst().ifPresent(organizeGeneralDetailVO -> attendanceGroupVo.setBindingOrgName(organizeGeneralDetailVO.getOrganizeTreeName()));
            }
        }
        //获取当前考勤组成员
        //查询人员数
        List<UserBoundVO> userBoundVO = attendanceUserService.getUserBoundVO(groupId, workGroupId);
        if (CollUtil.isEmpty(userBoundVO)) {
            return attendanceGroupVo;
        }
        FtbAttendanceLineSchedulingConfig lineSchedulingConfig = lineSchedulingConfigService.getByGroupId(groupId);
        if (Objects.isNull(lineSchedulingConfig)) {
            return attendanceGroupVo;
        }
        List<String> allUserIds = userBoundVO.stream().map(UserBoundVO::getId).distinct().collect(Collectors.toList());
        //查询人员数
        StaffRosterListReq staffRosterListReq = new StaffRosterListReq();
        staffRosterListReq.setPageSize(-1);
        staffRosterListReq.setIsQueryAuth("0");
        staffRosterListReq.setUserIds(allUserIds);
        ActionResult<PageListVO<FtbPersonnelsStaffRosterDto>> pageListVOActionResult = ftbPersonnelsRosterManagerApi.postWithSalary(staffRosterListReq);
        PageListVO<FtbPersonnelsStaffRosterDto> data = pageListVOActionResult.getData();
        List<FtbPersonnelsStaffRosterDto> list = data.getList();
        if (CollUtil.isEmpty(list)) {
            return attendanceGroupVo;
        }
        List<String> workNatureArr = StringUtil.isEmpty(lineSchedulingConfig.getWorkNature()) ? List.of() : Arrays.asList(StringUtil.split(lineSchedulingConfig.getWorkNature(), ","));
        List<String> employeeTypeArr = StringUtil.isEmpty(lineSchedulingConfig.getEmployeeType()) ? List.of() : Arrays.asList(StringUtil.split(lineSchedulingConfig.getEmployeeType(), ","));
        List<String> positionArr = StringUtil.isEmpty(lineSchedulingConfig.getPosition()) ? List.of() : Arrays.asList(StringUtil.split(lineSchedulingConfig.getPosition(), ","));
        List<String> memberArr = StringUtil.isEmpty(lineSchedulingConfig.getMembers()) ? List.of() : Arrays.asList(StringUtil.split(lineSchedulingConfig.getMembers(), ","));
        if (CollUtil.isEmpty(workNatureArr) && CollUtil.isEmpty(employeeTypeArr) && CollUtil.isEmpty(positionArr) && !Objects.equals(lineSchedulingConfig.getMembersType(), 0) && CollUtil.isEmpty(memberArr)) {
            return attendanceGroupVo;
        }
        boolean hasOnboarding = workNatureArr.contains("301");
        List<String> userIdsForConfigFilter = list.stream()
                .filter(dto -> (CollUtil.isNotEmpty(workNatureArr) && workNatureArr.contains(dto.getWorkerStatus()))
                        && ((hasOnboarding && StringUtil.isEmpty(dto.getWorkerType())) || employeeTypeArr.contains("-1") || CollUtil.isNotEmpty(employeeTypeArr) && employeeTypeArr.contains(dto.getWorkerType()))
                        || (CollUtil.isNotEmpty(positionArr) && positionArr.contains(dto.getCurrPosition()))
                        || Objects.equals(lineSchedulingConfig.getMembersType(), 0)
                        || (CollUtil.isNotEmpty(memberArr) && memberArr.contains(dto.getUserId()))).map(FtbPersonnelsStaffRosterDto::getUserId).collect(Collectors.toList());
        attendanceGroupVo.setUserCount(userIdsForConfigFilter.size());
        return attendanceGroupVo;
    }

    @Override
    public void updateGroupOrg(AttendanceGroupOrgDto attendanceGroupOrgDto) {
        attendanceGroupMapper.updateGroupOrg(attendanceGroupOrgDto);
    }

    @Override
    public List<AttendanceUserGroupVo> getAttendanceUserGroup(List<String> userIds) {
        return attendanceGroupMapper.getAttendanceUserGroup(userIds);
    }

    @Override
    public void lockGroup(String groupId) {
        // 查询考勤组锁定状态
        AttendanceGroup group = attendanceGroupMapper.selectById(groupId);
        if (null != group) {
            Date date;
            AttendanceNoticeEnum noticeEnum;
            if (null == group.getLockedDate()) {
                // 锁定
                date = new Date();
                String dateStr = DateDetail.getDate2Str(date, DateDetail.DF);
                date = DateDetail.getStr2Date(dateStr);
                noticeEnum = AttendanceNoticeEnum.GROUP_LOCK;
            } else {
                date = null;
                noticeEnum = AttendanceNoticeEnum.GROUP_UNLOCK;
            }
            LambdaUpdateWrapper<AttendanceGroup> updateWrapper = new LambdaUpdateWrapper<AttendanceGroup>()
                    .set(AttendanceGroup::getLockedDate, date)
                    .eq(AttendanceGroup::getId, groupId);
            attendanceGroupMapper.update(null, updateWrapper);
            //发送解锁锁定通知
            UserInfo user = UserProvider.getUser();
            AttendanceNoticeModel attendanceNoticeModel = new AttendanceNoticeModel();
            attendanceNoticeModel.setTenantId(user.getTenantId());
            attendanceNoticeModel.setUserId(user.getUserId());
            attendanceNoticeModel.setAttendanceNoticeEnum(noticeEnum);
            attendanceNoticeModel.setGroupId(groupId);
            attendanceNoticeHandler.send(attendanceNoticeModel);
        }
    }

    @Override
    public GroupLockVo getUserCurrentGroupLockInfo(String userId) throws QueryException {

        // 查询用户当前所在的考勤组
        UserInfo userInfo = userProvider.get();
        UserInfo user = new UserInfo();
        user.setUserId(userId);
        user.setTenantId(userInfo.getTenantId());
        GroupInfoVo groupInfo = attendanceClockInService.getGroupInfoByDate(new Date(), user);
        return new GroupLockVo(groupInfo.getGroupId(), groupInfo.getLockedDate());
    }

    @Override
    public GroupLockVo getGroupLockInfo(String groupId) {

        Date groupLockDate = attendanceGroupMapper.getGroupLockDate(groupId);
        return new GroupLockVo(groupId, groupLockDate);
    }

    /**
     * 时间校验
     *
     * @param start         借调开始时间
     * @param end           借调结束时间
     * @param departureTime 离岗时间
     * @param backTime      回岗时间
     * @param userId        用户id
     *                      "startTime": "2023-12-10 10:00:00",
     *                      "endTime": "2023-12-12 10:00:00",
     *                      "departureTime": "2023-12-10 10:00:00",
     *                      "backTime": "2023-12-12 10:00:00"
     */
    private void checkSecondDate(List<String> timeJsons, Date start, Date end, Date departureTime, Date backTime, String userId) throws HandleException {
        for (String timeJson : timeJsons) {

            SecondmentDateVo secondmentDateVo = JsonUtil.getJsonToBean(timeJson, SecondmentDateVo.class);
            Date startTime = secondmentDateVo.getStartTime();
            Date endTime = secondmentDateVo.getEndTime();
            /* 时间比较 （借调开始时间>用户已被借调开始时间 && 借调结束时间<=用户已被借调结束时间） || 离岗时间-用户离岗时间*/
            Boolean startCompareStart = startTime != null && ((DateUtil.dateCompare(start, startTime) >= 0 && DateUtil.dateCompare(end, endTime) <= 0) || (DateUtil.dateCompare(departureTime, startTime) >= 0 && DateUtil.dateCompare(backTime, endTime) <= 0));
            /* 时间比较 用户借调开始时间<=用户已被借调结束时间 || 用户回岗时间<用户已被借调结束时间*/
            Boolean endCompareStart = endTime != null && ((DateUtil.dateCompare(start, endTime) <= 0 && DateUtil.dateCompare(end, endTime) >= 0) || (DateUtil.dateCompare(backTime, endTime) <= 0 && DateUtil.dateCompare(backTime, endTime) >= 0));
            if (startCompareStart || endCompareStart) {
//                UserEntity userEntity = userApi.getInfoById(userId);
                ActionResult<List<UserBoundVO>> userList = v2UserApi.getAllUserInfoBatch(Stream.of(userId).collect(Collectors.toList()), null);
                if (200 != userList.getCode() || CollectionUtil.isEmpty(userList.getData())) {
                    return;
                }
                throw new HandleException(userList.getData().get(0).getUserName() + "已被借调");
            }
        }
    }

    /**
     * 按照名称首字母排序
     */
    private void sortByName(List<AttendanceGroupVo> attendanceGroupVoList) {
        CollectionUtil.sort(attendanceGroupVoList, new Comparator<AttendanceGroupVo>() {
            @Override
            public int compare(AttendanceGroupVo o1, AttendanceGroupVo o2) {
                if (o1 == null && o2 == null) {
                    return -1;
                }
                String name1 = null;
                if (o1 != null) {
                    name1 = PinYinUtil.getPingYin(o1.getGroupName());
                }
                String name2 = PinYinUtil.getPingYin(o2.getGroupName());
                Character a = Objects.requireNonNull(name1).charAt(0);
                Character b = name2.charAt(0);
//                return o1.getGroupName().compareTo(o2.getGroupName());
                return a.compareTo(b);
            }
        });
    }


    /**
     * 考勤组管理列表组成递归树结构
     *
     * @return List<AttendanceGroupVo>
     */
    private List<AttendanceGroupVo> treeGroupVo(List<AttendanceGroupVo> groupVoList) {
        List<AttendanceGroupVo> topGroupList = groupVoList.stream().filter(group -> {
            return group.getParentId().equals("0");
        }).collect(Collectors.toList());

        return topGroupList.stream().peek(group -> group.setChild(recursiveQuery(group, groupVoList))).collect(Collectors.toList());
    }

    /**
     * 获取我管理的考勤组管理列表组成递归树结构
     *
     * @return List<AttendanceGroupVo>
     */
    private List<AttendanceGroupVo> treeMyManagerGroupVo(List<AttendanceGroupVo> allGroupList) {
        if (CollectionUtil.isEmpty(allGroupList)) {
            return allGroupList;
        }
        /* 排序 筛选顶层节点*/
        allGroupList.sort(new Comparator<AttendanceGroupVo>() {
            @Override
            public int compare(AttendanceGroupVo o1, AttendanceGroupVo o2) {
                Integer length1 = o1.getLevelCode().split("#").length;
                Integer length2 = o2.getLevelCode().split("#").length;
                return length1.compareTo(length2);
            }
        });

        /* 筛选顶层节点*/
        List<AttendanceGroupVo> topGroupVoList = allGroupList.stream().filter(group -> {
            String levelCode = group.getLevelCode();
            String[] split = levelCode.split("#");
            boolean flag = false;
            if (group.getParentId().equals("0")) {
                /* 如果本来就是根节点，则直接返回*/
                return true;
            }
            String parentLevelCode = levelCode.replace(split[0], "");
            List<String> groupIds = allGroupList.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());

            for (String groupId : groupIds) {
                flag = !parentLevelCode.contains(groupId);
                if (!flag) {
                    break;
                }
            }
            return flag;
        }).collect(Collectors.toList());
        List<AttendanceGroupVo> resultGroupTree = topGroupVoList.stream().peek(group -> group.setChild(recursiveQueryManagerGroup(group, allGroupList))).collect(Collectors.toList());
        GROUP_ID_LOCAL.remove();
//        groupIds.clear();
        return resultGroupTree;
    }


    /**
     * 迭代查询
     *
     * @return List<AttendanceGroupVo>
     */
    private List<AttendanceGroupVo> recursiveQuery(AttendanceGroupVo root, List<AttendanceGroupVo> groupVoList) {
        if (CollectionUtil.isEmpty(groupVoList)) {
            root.setChild(null);
        }
        List<AttendanceGroupVo> children = new ArrayList<>();
        groupVoList.forEach(item -> {
            if (Objects.equals(item.getParentId(), root.getId())) {
                item.setChild(recursiveQuery(item, groupVoList));
                children.add(item);
            }
        });
        return children;
    }

    private List<AttendanceGroupVo> recursiveQueryManagerGroup(AttendanceGroupVo root, List<AttendanceGroupVo> attendanceGroupVoList) {
        if (CollectionUtil.isEmpty(attendanceGroupVoList)) {
            root.setChild(null);
        }
        List<AttendanceGroupVo> children = new ArrayList<>();
        attendanceGroupVoList.forEach(item -> {
            String levelCode = item.getLevelCode();
            String parentLevelCode = root.getLevelCode();
            if (levelCode.contains(parentLevelCode)
                    && levelCode.length() > parentLevelCode.length()
                    && !GROUP_ID_LOCAL.get().contains(item.getId()))
//                    && !groupIds.contains(item.getId()))
            {

                item.setChild(recursiveQueryManagerGroup(item, attendanceGroupVoList));
                children.add(item);
                GROUP_ID_LOCAL.get().add(item.getId());
//                groupIds.add(item.getId());
            }
        });
        return children;
    }


    /**
     * 递归获取考勤组父级id
     */
    private void recursionParent(String parentId, List<AttendanceGroup> group) {
        AttendanceGroup parent = attendanceGroupMapper.selectById(parentId);
        if (parent == null) {
            return;
        }

        group.add(parent);
        recursionParent(parent.getParentId(), group);
    }

    /**
     * 考勤组及考勤组人员老数据处理
     */
    @Override
    public void oldDataProcessing(String tenantId) {
        log.error("更新租户[{}],考勤组及考勤组人员老数据处理开始", tenantId);
        //根据组织查询考勤组信息，如果未查询到组织对应考勤组，则根据组织名称创建考勤组
        //查询组织信息列表
        try {
            TenantDataSourceUtil.switchTenant(tenantId);
        } catch (LoginException e) {
            throw new RuntimeException(e);
        }
        List<String> orgIds = CollUtil.newArrayList();
        List<AttendanceGroup> list2 = lambdaQuery().orderByAsc(AttendanceGroup::getCreatorTime).list();
        Map<String, String> oldGroup2orgMap = list2.stream().filter(vo -> StringUtil.isNotEmpty(vo.getOrgId()) && (Objects.equals(vo.getDeleteMark(), 0) || StringUtil.equals(vo.getDeleteUserId(), "admin"))).collect(Collectors.toMap(AttendanceGroup::getId, AttendanceGroup::getOrgId, (r1, r2) -> r1));
        Map<String, String> org2GroupMap = batchSaveGroupByOrgIds(tenantId, orgIds);
        log.error("更新租户[{}],更新考勤组信息完成", tenantId);
        List<AttendanceGroup> list = lambdaQuery().eq(AttendanceGroup::getDeleteMark, Boolean.FALSE).orderByAsc(AttendanceGroup::getCreatorTime).list();
        Map<String, String> group2orgMap = list.stream().filter(vo -> StringUtil.isNotEmpty(vo.getOrgId())).collect(Collectors.toMap(AttendanceGroup::getId, AttendanceGroup::getOrgId, (r1, r2) -> r1));
        //原有考勤组 查询考勤组人员信息，如果人员信息不一致，多退少补
        List<AttendanceGroupUser> attendanceGroupUsers = attendanceUserService.queryAll();
        ActionResult<List<UserBoundVO>> listActionResult1 = v2UserApi.listTargetOrganizesOrHaveChild(orgIds, false, List.of(UserWorkStatusEnums.RESIGNED), tenantId);
        List<UserBoundVO> userList = listActionResult1.getData();
        Map<String, Date> collect1 = userList.stream().filter(vo->Objects.nonNull(vo.getEntryDate())).collect(Collectors.toMap(UserBoundVO::getId, UserBoundVO::getEntryDate, (r1, r2) -> r1));
        //过滤存在于原有考勤组的组织的人员信息，并根据组织分组
        Map<String, List<UserBoundVO>> collect3 = userList.stream().collect(Collectors.groupingBy(UserBoundVO::getOrganizeId));
        collect3.forEach((orgId, users) -> {
            String groupId = org2GroupMap.get(orgId);
            //获取在其他非借调考勤组的本组织成员,移动到当前考勤组下
            List<AttendanceGroupUser> groupUsers = attendanceGroupUsers.stream().filter(vo -> Objects.equals(vo.getType(), 1) && users.stream().anyMatch(user -> user.getId().contains(vo.getUserId()))).collect(Collectors.toList());
            groupUsers.forEach(vo -> {
                vo.setGroupId(groupId);
            });
            //获取非组织绑定考勤组下成员
            List<String> userIds = users.stream().map(UserBoundVO::getId).filter(userId -> groupUsers.stream().noneMatch(groupUser -> groupUser.getUserId().equals(userId))).collect(Collectors.toList());
            //获取在其他借调考勤组的本组织成员,移动到目标组织考勤组
            attendanceGroupUsers.stream().filter(vo -> Objects.equals(vo.getType(), 2) && userIds.contains(vo.getUserId())).forEach(vo -> {
                vo.setGroupId(org2GroupMap.get(group2orgMap.getOrDefault(vo.getGroupId(), "")));
            });
            //不在考勤组的本组织成员，则创建考勤组成员信息
            List<AttendanceGroupUser> collect4 = userIds.stream()
                    .filter(userId -> groupUsers.stream().noneMatch(groupUser -> groupUser.getUserId().equals(userId)))
                    .map(userId -> {
                        AttendanceGroupUser attendanceGroupUser = new AttendanceGroupUser();
                        attendanceGroupUser.setId(RandomUtil.uuId());
                        attendanceGroupUser.setGroupId(groupId);
                        attendanceGroupUser.setUserId(userId);
                        attendanceGroupUser.setType(1);
                        attendanceGroupUser.setCreatorTime(collect1.getOrDefault(userId, new Date()));
                        attendanceGroupUser.setCreatorUserId("admin");
                        attendanceGroupUser.setTenantId(tenantId);
                        attendanceGroupUser.setDeleteMark(0);
                        attendanceGroupUser.setSort(10000);
                        attendanceGroupUser.setUserGroupType(1);
                        return attendanceGroupUser;
                    }).collect(Collectors.toList());
            attendanceGroupUsers.addAll(collect4);
        });
        attendanceUserService.saveOrUpdateBatch(attendanceGroupUsers);
        List<AttendanceGroupUser> collect = collect3.entrySet().stream().flatMap(entry -> {
            String groupId = org2GroupMap.get(entry.getKey());
            if (StringUtil.isEmpty(groupId)) {
                return Stream.empty();
            }
            //清除非本考勤组成员
            return attendanceGroupUsers.stream().filter(vo -> StringUtil.equals(groupId, vo.getGroupId()) && Objects.equals(vo.getType(), 1) && entry.getValue().stream().noneMatch(user -> user.getId().contains(vo.getUserId())));
        }).collect(Collectors.toList());
        attendanceUserService.removeBatchByIds(collect);
        //调整groupUser离职数据
        List<AttendanceGroupUser> list1 = attendanceUserService.list(new LambdaQueryWrapper<AttendanceGroupUser>().eq(AttendanceGroupUser::getDeleteMark, 1));
        list1.forEach(vo -> vo.setGroupId(org2GroupMap.get(oldGroup2orgMap.getOrDefault(vo.getGroupId(), ""))));
        attendanceUserService.updateBatchById(list1);
        attendanceGroupUsers.removeAll(collect);
        Map<String, List<AttendanceGroupUser>> usersMap = attendanceGroupUsers.stream().collect(Collectors.groupingBy(AttendanceGroupUser::getUserId));
        log.error("更新租户[{}],更新考勤组人员信息完成", tenantId);
        attendanceDailyRuleService.hisDailyRule(oldGroup2orgMap, org2GroupMap, usersMap);
        log.error("更新租户[{}],更新考勤规则信息完成", tenantId);
        attendanceBaseSettingService.hisBaseSetting(oldGroup2orgMap, org2GroupMap);
        log.error("更新租户[{}],更新考勤组基础信息完成", tenantId);
        attendanceLocationSettingService.hisLocationSetting(oldGroup2orgMap, org2GroupMap);
        log.error("更新租户[{}],更新考勤组考勤地点信息完成", tenantId);
        attendanceShiftSettingService.hisShiftSetting(oldGroup2orgMap, org2GroupMap);
        log.error("更新租户[{}],更新考勤组班次规则信息完成", tenantId);
        // 组织重构考勤数据变更
//        attendanceDayStatisticsService.regenerateDayData(tenantId);
    }

    @Override
    @Transactional
    public Map<String, String> batchSaveGroupByOrgIds(String tenantId, List<String> orgIds) {
        QueryOrganizeListTargetTypesDTO queryOrganizeListTargetTypesDTO = new QueryOrganizeListTargetTypesDTO(List.of(OrganizeCategoryEnums.COMPANY, OrganizeCategoryEnums.DEPARTMENT, OrganizeCategoryEnums.STORE));
        queryOrganizeListTargetTypesDTO.setOrganizeIds(orgIds);
        queryOrganizeListTargetTypesDTO.setTenantId(tenantId);
        ActionResult<List<OrganizeGeneralDetailVO>> listActionResult = v2OrganizeApi.listOrganizeByTargetTypes(queryOrganizeListTargetTypesDTO);
        List<OrganizeGeneralDetailVO> data = listActionResult.getData();
        Map<String, String> org2Parent = data.stream().collect(Collectors.toMap(OrganizeGeneralDetailVO::getId, OrganizeGeneralDetailVO::getParentId, (r1, r2) -> r1));
        orgIds.clear();
        orgIds.addAll(data.stream().flatMap(vo -> Stream.of(vo.getId(), vo.getParentId())).distinct().collect(Collectors.toList()));
        List<AttendanceGroup> list = lambdaQuery().eq(AttendanceGroup::getDeleteMark, Boolean.FALSE).in(CollUtil.isNotEmpty(orgIds), AttendanceGroup::getOrgId, orgIds).orderByAsc(AttendanceGroup::getCreatorTime).list();
        Map<String, String> org2group = list.stream().collect(Collectors.toMap(AttendanceGroup::getOrgId, AttendanceGroup::getId, (r1, r2) -> r1));
        //查询每个组织下人员
        Map<String, String> orgNameMap = data.stream().collect(Collectors.toMap(OrganizeGeneralDetailVO::getId, OrganizeGeneralDetailVO::getName));
        List<AttendanceGroup> collect1 = data.stream()
                .filter(vo -> !org2group.containsKey(vo.getId()))
                .sorted(Comparator.comparing(OrganizeGeneralDetailVO::getTires))
                .map(vo -> {
                    AttendanceGroup attendanceGroup = new AttendanceGroup();
                    attendanceGroup.setId(RandomUtil.uuId());
                    attendanceGroup.setAttendanceClassSetting(0);
                    attendanceGroup.setAttendancePointsSetting(0);
                    attendanceGroup.setBaseSetting(0);
                    attendanceGroup.setDeleteMark(0);
                    attendanceGroup.setDetailName(vo.getName());
                    attendanceGroup.setFestivalSetting(0);
                    attendanceGroup.setGpsEnable(0);
                    attendanceGroup.setHolidaySetting(0);
                    attendanceGroup.setLeaveSetting(0);
                    attendanceGroup.setGroupName(vo.getName());
                    attendanceGroup.setOrgId(vo.getId());
                    attendanceGroup.setParentId(org2group.getOrDefault(vo.getParentId(), "000000"));
                    attendanceGroup.setWifiEnable(0);
                    List<String> organizeIdTree = Arrays.stream(vo.getOrganizeIdTree().split(",")).collect(Collectors.toList());
                    List<String> levelCodes = organizeIdTree.stream().map(parentId -> org2group.getOrDefault(parentId, "000000")).sorted((Comparator.reverseOrder())).collect(Collectors.toList());
                    List<String> detailName = organizeIdTree.stream().map(parentId -> orgNameMap.getOrDefault(parentId, "")).sorted((Comparator.reverseOrder())).collect(Collectors.toList());
                    attendanceGroup.setLevelCode(StringUtil.join(levelCodes, "#"));
                    attendanceGroup.setDetailName(StringUtil.join(detailName, "/"));
                    attendanceGroup.setTenantId(tenantId);
                    attendanceGroup.setCreatorTime(new Date());
                    attendanceGroup.setCreatorUserId("admin");
                    org2group.put(vo.getId(), attendanceGroup.getId());
                    return attendanceGroup;
                }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect1)) {
            saveBatch(collect1);
            redisTemplate.delete(String.format(ATTENDANCE_BASE_SETTING_CACHE_KEY, tenantId));
        }
        if (CollUtil.isNotEmpty(list)) {
            list.forEach(group -> {
                        String groupId = org2group.get(group.getOrgId());
                        if (StringUtil.equals(groupId, group.getId())) {
                            group.setGroupName(orgNameMap.getOrDefault(group.getOrgId(), group.getGroupName()));
                            group.setParentId(org2group.getOrDefault(org2Parent.getOrDefault(group.getOrgId(), "000000"), group.getParentId()));
                            return;
                        }
                        group.setDeleteMark(1);
                        group.setDeleteUserId("admin");
                    }
            );
            updateBatchById(list);
            redisTemplate.delete(String.format(ATTENDANCE_BASE_SETTING_CACHE_KEY, tenantId));
        }
        return org2group;
    }

    /**
     * 递归获取考勤组父级id
     */
    private String recursionParent(String levelCode) {
        if (StringUtil.isEmpty(levelCode)) {
            return "";
        }
        List<String> groupIds = Arrays.stream(levelCode.split("#")).collect(Collectors.toList());
        List<AttendanceGroup> list = lambdaQuery().in(AttendanceGroup::getId, groupIds).eq(AttendanceGroup::getDeleteMark, Boolean.FALSE).list();
        if (CollUtil.isEmpty(list)) {
            return "";
        }
        return list.stream().sorted(Comparator.comparing(AttendanceGroup::getCreatorTime)).map(AttendanceGroup::getGroupName).reduce((r1, r2) -> r1 + "/" + r2).orElse("");
    }

    /**
     * 获取组织下考勤组
     *
     * @return List<AttendanceGroup>
     */
    @Override
    public List<AttendanceGroup> getByOrgId(String organizeId) {
        QueryWrapper<AttendanceGroup> groupQuery = new QueryWrapper<>();
        groupQuery.lambda()
                .eq(AttendanceGroup::getOrgId, organizeId)
                .eq(AttendanceGroup::getDeleteMark, 0);
        return attendanceGroupMapper.selectList(groupQuery);
    }

    /**
     * 获取组织下考勤组
     *
     * @param organizeIds
     * @return List<AttendanceGroup>
     */
    @Override
    public List<AttendanceGroup> getByOrgIds(List<String> organizeIds) {
        QueryWrapper<AttendanceGroup> groupQuery = new QueryWrapper<>();
        groupQuery.lambda()
                .in(AttendanceGroup::getOrgId, organizeIds)
                .eq(AttendanceGroup::getDeleteMark, 0);
        List<AttendanceGroup> groups = attendanceGroupMapper.selectList(groupQuery);
        return groups;
    }

    @Override
    public List<AttendanceUserListGroupVO> getAttendanceUserListGroupVO(List<String> userIds) {
        List<AttendanceGroup> allAttendanceGroup = this.list();
        List<AttendanceUserListGroupVO> userListGroupVOS = attendanceGroupMapper.getAttendanceUserListGroupVO(userIds);
        if (CollUtil.isEmpty(allAttendanceGroup) || CollUtil.isEmpty(userListGroupVOS)) {
            return new ArrayList<>();
        }
        userListGroupVOS.forEach(userGroup -> {
            StringBuffer fullName = new StringBuffer();
            getFullGroupName(allAttendanceGroup, userGroup.getGroupId(), userGroup.getGroupId(), fullName);
            userGroup.setGroupFullName(fullName.toString());
        });

        return userListGroupVOS;
    }

    @Override
    public AttendanceGroupVo getAttendanceGroupByNameOrganizeAndGroup(String organizeName, String groupName) {
//        OrganizeEntity organize = organizeApi.getByFullName(organizeName);
        OrganizeGeneralDetailVO organizeGeneralDetailVO = v2OrganizeApi.organizeInfoByName(OrganizeCategoryEnums.DEPARTMENT, organizeName);
        if (organizeGeneralDetailVO == null) {
            return null;
        }
        List<AttendanceGroupVo> attendanceGroupVos = this.groupListByOrgId(organizeGeneralDetailVO.getId());
        if (CollUtil.isEmpty(attendanceGroupVos)) {
            return null;
        }
        return attendanceGroupVos.stream().filter(data -> data.getGroupName().equals(groupName)).findFirst().orElse(null);
    }

    /**
     * 获取考勤组全名称  xxx/xxx/xxx
     *
     * @param allAttendanceGroup 所有考勤组, 方便迭代,提高检索效率,避免多次sql
     * @param groupId            目标考勤组id
     * @param thisGroup          当前位置考勤组id
     * @param fullName           考勤组全名
     */
    private void getFullGroupName(List<AttendanceGroup> allAttendanceGroup, String groupId, String thisGroup, StringBuffer fullName) {
        AttendanceGroup thisAttendanceGroup = allAttendanceGroup.stream().filter(group -> group.getId().equals(thisGroup)).findFirst().orElse(null);
        if (thisAttendanceGroup != null) {
            //是否是顶级考勤组
            if (thisAttendanceGroup.getParentId().equals("0")) {
                fullName.insert(0, thisAttendanceGroup.getGroupName().concat("/"));
            } else {
                if (thisAttendanceGroup.getId().equals(groupId)) {
                    fullName.append(thisAttendanceGroup.getGroupName());
                    getFullGroupName(allAttendanceGroup, groupId, thisAttendanceGroup.getParentId(), fullName);
                } else {
                    fullName.insert(0, thisAttendanceGroup.getGroupName().concat("/"));
                    getFullGroupName(allAttendanceGroup, groupId, thisAttendanceGroup.getParentId(), fullName);
                }
            }
        }

    }

    @Override
    public List<AttendanceGroup> getUserCurrentGroups(String userId) {
        // 获取当前时间
        Date now = new Date();

        // 查询当前时间用户所在的考勤组关联信息（包含借调）
        List<AttendanceGroupUser> groupUsers = attendanceUserService.getAttendanceGroupUsersOfSecondment(
                now, now, Collections.singletonList(userId), null);

        if (CollUtil.isEmpty(groupUsers)) {
            return Collections.emptyList();
        }

        // 提取考勤组ID列表
        List<String> groupIds = groupUsers.stream()
                .map(AttendanceGroupUser::getGroupId)
                .filter(StrUtil::isNotBlank)
                .distinct()
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(groupIds)) {
            return Collections.emptyList();
        }

        // 查询考勤组详细信息
        return this.listByIds(groupIds);
    }
}
