package jnpf.personnels.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fantaibao.permission.handling.PermissionHandling;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import io.seata.spring.annotation.GlobalTransactional;
import jnpf.account.PTenantAccountApi;
import jnpf.attendance.dto.AttendanceUserGroupVo;
import jnpf.attendance.dto.GroupUpdateByUserDTO;
import jnpf.attendance.service.AttendanceGroupService;
import jnpf.attendance.service.AttendanceUserFaceService;
import jnpf.authority.service.FtbPermissionRoleAuthorizePersonService;
import jnpf.authority.utils.PermissionsApplicableEnums;
import jnpf.authority.utils.PermissionsApplicableObject;
import jnpf.authority.utils.PermissionsEnums;
import jnpf.authority.utils.PermissionsUtils;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.vo.PageListVO;
import jnpf.certificate.service.CertificateInstanceService;
import jnpf.cultivate.service.FtbCultivatePromotionNewService;
import jnpf.engine.FlowTaskApi;
import jnpf.enums.personnel.SalaryApplyTypeEnum;
import jnpf.file.FileApi;
import jnpf.model.attendance.dto.UserFaceDto;
import jnpf.model.certificate.vo.app.HealthCertificateDetailVO;
import jnpf.model.cultivate.CultivatePage;
import jnpf.model.cultivate.dto.offline.FtbCultivateOfflineFileDTO;
import jnpf.model.cultivate.resp.CanDeleteMsg;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionWithPersonelVO;
import jnpf.model.enums.*;
import jnpf.model.im.UserAndLinkDTO;
import jnpf.model.personnels.bo.ExportRosterOneVo;
import jnpf.model.personnels.bo.FtbRosterImportTemplateBO;
import jnpf.model.personnels.dto.regular.FtbPersonnelsRegularCreateDTO;
import jnpf.model.personnels.dto.roster.FtbjobTrialRejectedDTO;
import jnpf.model.personnels.dto.roster.QueryCompanyAgeDto;
import jnpf.model.personnels.dto.salary.FtbPersonnelsSalaryInfo;
import jnpf.model.personnels.dto.staff.field.ExportFormTypeDto;
import jnpf.model.personnels.dto.staff.field.FormFieldDto;
import jnpf.model.personnels.dto.staff.field.FormTypeDto;
import jnpf.model.personnels.dto.staff.growth.AddGrowthLogDto;
import jnpf.model.personnels.dto.staff.registerform.GroupFieldDataDto;
import jnpf.model.personnels.dto.staff.registerform.ProbationPeriodDto;
import jnpf.model.personnels.dto.staff.registerform.WorkAddressDto;
import jnpf.model.personnels.dto.staff.roster.*;
import jnpf.model.personnels.dto.staff.salarylog.AddSalaryChangeLogDto;
import jnpf.model.personnels.po.*;
import jnpf.model.personnels.req.roster.*;
import jnpf.model.personnels.vo.roster.*;
import jnpf.model.personnels.vo.salary.UserInfoWithSalary;
import jnpf.model.store.vo.StoreUserRelationVo;
import jnpf.model.user.GenerateHeadFileForm;
import jnpf.permission.*;
import jnpf.permission.dto.QueryUserListDTO;
import jnpf.permission.dto.SaveUserManagerAddDTO;
import jnpf.permission.dto.SynUserBoundRoleDTO;
import jnpf.permission.dto.UpdateUserManagerBoundDTO;
import jnpf.permission.dto.relation.BaseUserPrimaryPositionDTO;
import jnpf.permission.dto.v2.user.QueryPageUserDTO;
import jnpf.permission.dto.v2.user.QueryUserBatchDTO;
import jnpf.permission.dto.v2.user.UpdateUserDTO;
import jnpf.permission.entity.OrganizeEntity;
import jnpf.permission.entity.PositionEntity;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.model.position.PositionGradesInfoVO;
import jnpf.permission.model.user.*;
import jnpf.permission.vo.contract.ContractTypeVO;
import jnpf.permission.vo.user.UserBasicWithMoreBoundVO;
import jnpf.permission.vo.user.UserBoundPhoneVO;
import jnpf.permission.vo.user.UserListMatchVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.permission.vo.v2.user.UserPageListVO;
import jnpf.permission.vo.v2.user.V2UserListMatchVO;
import jnpf.personnels.mapper.FtbPersonnelsStaffArchivesHistoryMapper;
import jnpf.personnels.mapper.FtbPersonnelsStaffRegistrationFormDataMapper;
import jnpf.personnels.mapper.FtbPersonnelsStaffRosterMapper;
import jnpf.personnels.mapper.FtbPersonnelsTurnoverManagementMapper;
import jnpf.personnels.service.*;
import jnpf.personnels.utils.*;
import jnpf.util.Constants;
import jnpf.util.JsonUtil;
import jnpf.util.SelfGrowthUtil;
import jnpf.util.UserProvider;
import jnpf.utils.FeignHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FtbPersonnelsStaffRosterServiceImpl extends ServiceImpl<FtbPersonnelsStaffRosterMapper, FtbPersonnelsStaffRoster> implements FtbPersonnelsStaffRosterService {
    @Autowired
    private OrganizeApi organizeApi;

    @Autowired
    private PositionApi positionApi;

    @Autowired
    private UserApi userApi;

    @Autowired
    private FtbPersonnelsStaffRegistrationFormDataService registrationFormDataService;

    @Autowired
    private FtbPermissionRoleAuthorizePersonService ftbPermissionRoleAuthorizePersonService;

    @Autowired
    private FtbPersonnelsStaffEmploymentApplyService staffEmploymentApplyService;

    @Autowired
    private FtbPersonnelsStaffSalaryChangeLogService salaryChangeLogService;

    @Autowired
    private FtbPersonnelsStaffGrowthLogService growthLogService;

    @Autowired
    private PersonnelOrgUtils personnelOrgUtils;

    @Autowired
    private PTenantAccountApi pTenantAccountApi;

    @Autowired
    private FtbPersonnelsRegistrationFormFieldOptionService fieldOptionService;

    @Autowired
    private FtbPersonnelsAuditRunTaskService ftbPersonnelsAuditRunTaskService;

    @Autowired
    private FtbPersonnelsRegularManagementService regularManagementService;

    @Autowired
    private FtbPersonnelsPermissionsService personnelsPermissionsService;
    @Autowired
    private PersonnelPerUtils personnelPerUtils;

    @Autowired
    private FtbPersonnelsSalaryService personnelSalaryService;

    private static final String DEFAULT_USER_LOGO = "001.png";
    private static final String ACCOUNT_TEMP_PRE = "tmp";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    FtbPersonnelsTurnoverManagementMapper turnoverManagementMapper;

    @Autowired
    FtbCultivatePromotionNewService promotionService;

    @Autowired
    private PersonnelAsyncOldData personnelAsyncOldData;


    @Autowired
    private PersonnelPreTrailIMUtils personnelPreTrailIMUtils;

    @Resource
    private AttendanceUserFaceService attendanceUserFaceService;
    @Resource
    private FileApi fileApi;
    @Resource
    private AttendanceGroupService attendanceGroupService;

    @Autowired
    private PersonnelAsyncServiceUtils personnelAsyncServiceUtils;

    @Autowired
    private FtbPersonnelsStaffArchivesHistoryService ftbPersonnelsStaffArchivesHistoryService;

    @Autowired
    FtbPersonnelsSalaryService personnelSalaryServiceImpl;
    @Autowired
    private FtbPersonnelsTurnoverManagementService turnoverManagementService;

    @Autowired
    private PersonnelAsyncImportUtils personnelAsyncImportUtils;
    @Autowired
    private FtbPersonnelsRegistrationFormFieldService registrationFormFieldService;

    @Autowired
    private FlowTaskApi flowTaskApi;

    @Autowired
    FtbPersonnelsStaffArchivesHistoryMapper staffArchivesHistoryMapper;

    @Autowired
    private Executor threadPoolExecutor;

    @Autowired
    FtbPersonnelsStaffRegistrationFormDataMapper dataMapper;

    @Autowired
    UserPrimaryPositionApi userPrimaryPositionApi;

    @Autowired
    private PermissionsUtils permissionsUtils;

    @Autowired
    private RosterExportUtils rosterExportUtils;

    @Autowired
    private V2UserApi v2UserApi;

    @Resource
    private PermissionHandling permissionHandling;

    @Value("${invite-url}")
    private String joinUrl;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    FtbPersonnelsSecondmentManagementService secondmentManagementService;

    @Resource
    private CertificateInstanceService certificateInstanceService;


    private final static List<String> mainTableField = Arrays.asList("id", "userId", "systemWokerId", "systemContractId", "name", "phone", "workerNo", "entrySalary",
            "regularSalary", "workerType", "joinNum", "actualProbationaryDate", "actualStartDate", "isTrialJob", "trialJobDay", "isSignSeparation", "workerStatus");

    private final static List<String> extTableField = Arrays.asList("userRoleList", "orgList", "currReportsTo", "currReportsToName", "attendanceGroup", "attendanceGroupName", "currSalary");

    @Override
    public PageInfo<FtbPersonnelsStaffRosterDto> getPageList(StaffRosterListReq req, Boolean isExport) {
        if (StringUtils.isNotEmpty(req.getKeyWord())) {
            req.setKeyWord(StringUtils.trim(req.getKeyWord()));
        }
        if (StringUtils.isNotEmpty(req.getWorkerType())) {
            String[] split = req.getWorkerType().split(",");
            req.setWorkerTypeList(Arrays.asList(split));
        }
        //查询用户数据权限
        List<String> userList = new ArrayList<>();
        boolean isAdministrator = false;
        if (!"0".equals(req.getIsQueryAuth())) {
            List<String> authUserList = queryCacheAuthUserList(PermissionsEnums.PERSONNEL_MANAGEMENT_WEB.getValue(), null);
            // 非超级管理员但是无数据
            if (authUserList != null && authUserList.isEmpty()) {
                return new PageInfo<>(new ArrayList<>());
            }
            if (CollectionUtil.isNotEmpty(authUserList)) userList.addAll(authUserList);
            isAdministrator = authUserList == null;
        }
        String currOrg = req.getCurrOrg();
        if (StringUtils.isNotEmpty(currOrg)) {
            QueryPageUserDTO dto = new QueryPageUserDTO();
            dto.setOrganizeIds(List.of(currOrg.split(",")));
            dto.setIsPage(false);
            dto.setPositionId(req.getCurrPosition());
            dto.setGradeId(req.getCurrRank());
            ActionResult<PageListVO<UserBoundVO>> listByLevel = v2UserApi.pagePost(dto);
            List<String> userSubQueryList = listByLevel.getCode() == 200 ?
                    listByLevel.getData().getList().stream().map(UserBoundVO::getId).collect(Collectors.toList())
                    : new ArrayList<>();
            if (CollectionUtil.isEmpty(userList)) {
                if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                    userList = userSubQueryList;
                } else {
                    return new PageInfo<>(new ArrayList<>());
                }
            } else {
                if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                    userList = userList.stream()
                            .filter(userSubQueryList::contains)
                            .collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(userList)) {
                        return new PageInfo<>(new ArrayList<>());
                    }
                } else {
                    return new PageInfo<>(new ArrayList<>());
                }
            }
        }
        // 健康证状态筛选
        if (req.getHealthCertificateStatus() != null) {
            List<String> healthCertificateUserIds = certificateInstanceService.getHealthCertificateUserIdsByStatus(req.getHealthCertificateStatus());
            if (CollUtil.isNotEmpty(healthCertificateUserIds)) {
                // 超管，状态无人
                if (UserProvider.getUser().getIsAdministrator()) {
                    userList.addAll(healthCertificateUserIds);
                } else {
                    userList = userList.stream()
                            .filter(healthCertificateUserIds::contains)
                            .collect(Collectors.toList());
                }
                if (CollectionUtil.isEmpty(userList)) {
                    return new PageInfo<>(new ArrayList<>());
                }
            } else {
                return new PageInfo<>(new ArrayList<>());
            }
        }
        // 补充生日筛选区间
        String startBirthdayTime = req.getStartBirthdayTime();
        String endBirthdayTime = req.getEndBirthdayTime();
        if (startBirthdayTime != null && endBirthdayTime != null) {
            // 只去月份+日期
            List<String> phoneNumber = baseMapper.queryBirthday(startBirthdayTime, endBirthdayTime);
            if (CollUtil.isNotEmpty(phoneNumber)) {
                req.setPhoneNumberList(phoneNumber);
            } else {
                return new PageInfo<>(new ArrayList<>());
            }
        }
        // 添加自定义查询用户
        if (CollUtil.isNotEmpty(req.getUserIds())) {
            List<String> list = req.getUserIds();
            userList.addAll(list);
        }
        Page<FtbPersonnelsStaffRosterDto> queryPage = baseMapper.pagingQuery(
                Page.of(req.getCurrentPage(), req.getPageSize()),
                req, userList);
        List<FtbPersonnelsStaffRosterDto> records = queryPage.getRecords();
        if (CollectionUtil.isNotEmpty(records) && !isExport) {
            fillContractTypeName(records);//补充合同类型名称
            fillAllUserOrgInfo(records, false);
            fillFormDataRoster(records, false);
            List<String> userIds = records.stream().map(FtbPersonnelsStaffRosterDto::getUserId).collect(Collectors.toList());
            List<HealthCertificateDetailVO> healthCertificateDetails = certificateInstanceService.getHealthCertificateDetails(userIds);
            Map<String, HealthCertificateDetailVO> healthCertificateDetailMap = healthCertificateDetails.stream()
                    .collect(Collectors.toMap(HealthCertificateDetailVO::getUserId, v -> v));
            records.forEach(item -> {
                //
                if ("304".equals(item.getWorkerStatus())) {
                    LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaQuery = Wrappers.lambdaQuery();
                    lambdaQuery.eq(FtbPersonnelsTurnoverManagement::getUserId, item.getUserId());
                    lambdaQuery.eq(FtbPersonnelsTurnoverManagement::getEnableMark, 0);
                    lambdaQuery.last("limit 1");
                    FtbPersonnelsTurnoverManagement management = turnoverManagementMapper.selectOne(lambdaQuery);
                    if (management != null && management.getTurnoverStatus() == 6) {
                        item.setTurnoverStatusFlag("1");
                    } else {
                        item.setTurnoverStatusFlag("");
                    }
                }
                // 健康证状态回填
                HealthCertificateDetailVO healthCertificateDetail = healthCertificateDetailMap.get(item.getUserId());
                if (healthCertificateDetail != null) {
                    item.setHealthCertificateStatus(healthCertificateDetail.getStatus());
                }
            });
        }
        //构建分页返回数据
        PageInfo<FtbPersonnelsStaffRosterDto> pageInfo = new PageInfo<>();
        pageInfo.setList(records);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }

    @Override
    public PageInfo<FtbPersonnelsStaffRosterDto> postWithSalary(StaffRosterListReq req) {
        Integer pageSize = req.getPageSize();
        Integer currentPage = req.getCurrentPage();
        Page<FtbPersonnelsStaffRosterDto> page = new Page();
        page.setSize(pageSize);
        page.setCurrent(currentPage);
        //薪酬的筛选单独处理
        //查询用户数据权限
        List<String> userList = new ArrayList<>();
        String isQueryAuth = req.getIsQueryAuth();
        if (CollUtil.isNotEmpty(req.getUserIds())) {
            userList = req.getUserIds();
        }
        if (!"0".equals(isQueryAuth)){
            if (!UserProvider.getUser().getIsAdministrator()) {
                List<String> authUserList = queryCacheAuthUserList(req.getModuleCode(), req.getCategory());
                if (CollectionUtil.isNotEmpty(authUserList)) {
                    List<String> finalUserList = userList;
                    // 筛选出当前用户权限下的用户
                    userList = authUserList.stream().filter(v -> {
                        if (CollUtil.isEmpty(finalUserList)) return true;
                        if (finalUserList.contains(v)) {
                            return true;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());
                    if  (CollUtil.isEmpty(userList)) {
                        return new PageInfo<>(new ArrayList<>());
                    }
                }
            }
            String targetOrganizeId = req.getTargetOrganizeId();
            String targetPositionId = req.getTargetPositionId();
            if (StringUtils.isNotEmpty(targetOrganizeId)) {
                QueryPageUserDTO dto = new QueryPageUserDTO();
                dto.setOrganizeIds(List.of(targetOrganizeId.split(",")));
                dto.setIsPage(false);
                dto.setPositionId(targetPositionId);
                ActionResult<PageListVO<UserBoundVO>> listByLevel = v2UserApi.pagePost(dto);
                List<String> userSubQueryList = listByLevel.getCode() == 200 ?
                        listByLevel.getData().getList().stream().map(UserBoundVO::getId).collect(Collectors.toList())
                        : new ArrayList<>();
                Collection<String> intersection = CollectionUtil.intersection(userSubQueryList, userList);
                if (CollectionUtil.isEmpty(userList)) {
                    if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                        userList = userSubQueryList;
                    } else {
                        return new PageInfo<>(new ArrayList<>());
                    }
                } else {
                    if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                        userList = userList.stream()
                                .filter(userSubQueryList::contains)
                                .collect(Collectors.toList());
                        if (CollectionUtil.isEmpty(userList)) {
                            return new PageInfo<>(new ArrayList<>());
                        }
                    } else {
                        return new PageInfo<>(new ArrayList<>());
                    }
                }
            }
            List<String>  orgIds = null;
            List<String> turUserIds = null;
            List<String> filteOrgIds =  StringUtils.isNotEmpty(targetOrganizeId) ? Arrays.asList(targetOrganizeId.split(",")) : null;
            if (!UserProvider.getUser().getIsAdministrator() ) {
                // 数据权限userIds
                orgIds =  permissionsUtils.obtainPersonnelOrganizationIdDataPermissions(UserProvider.getUser().getUserId(),req.getModuleCode(), req.getCategory());
                PermissionsApplicableObject permissionsApplicableObject = permissionsUtils.obtainTheScopeOfUserPermissionsEnums(UserProvider.getUser().getUserId());
                // 数据权限 仅下属单独处理
                if (permissionsApplicableObject.getPermissionsApplicableEnums() == PermissionsApplicableEnums.SCOPE_SUBORDINATE){
                    // 查询当前登录人的下属
                    turUserIds = inquireAboutSubordinates(UserProvider.getUser().getUserId());
                } else {
                    if ( orgIds != null ) {
                        turUserIds = doEmployeesOfYourOrganizationTur(orgIds, targetPositionId);
                    }
                }
            }
            if (filteOrgIds != null || StrUtil.isNotBlank(targetPositionId)){
                if (CollUtil.isNotEmpty(filteOrgIds) && CollUtil.isNotEmpty(orgIds)) {
                    assert orgIds != null;
                    orgIds = orgIds.stream().filter(filteOrgIds::contains).collect(Collectors.toList());
                }else if (CollUtil.isNotEmpty(filteOrgIds) && orgIds == null) {
                    orgIds =filteOrgIds;
                }
                turUserIds = doEmployeesOfYourOrganizationTur(orgIds,targetPositionId);
            }
            if (CollUtil.isNotEmpty(turUserIds)) {
                if (turUserIds.get(0).equals("-1")) {
                    //组织/岗位筛选无数据
                    userList = turUserIds;
                }else {
                    if (!UserProvider.getUser().getIsAdministrator() && (StrUtil.isNotBlank(targetPositionId) || StrUtil.isNotBlank(targetOrganizeId))) {
                        Collection<String> intersection = CollectionUtil.intersection(userList, turUserIds);
                        // 离职人员
                        Collection<String> subtract = CollectionUtil.subtract(turUserIds, userList);
                        // 合并交集与差集
                        List<String> mergedList = new ArrayList<>(intersection);
                        mergedList.addAll(subtract);
                        userList = mergedList;
                        if (CollectionUtil.isEmpty(userList)) {
                            userList.add("-1");
                        }
                    }else {
                        userList.addAll(turUserIds);
                    }
                }
            }
        }
        Page<FtbPersonnelsStaffRosterDto> list = baseMapper.pagingQueryNewWithTurnoverManagerList(req, userList, page);
        List<FtbPersonnelsStaffRosterDto> records = list.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            //补充组织 岗位 职等 信息 列表不在查询入职的组织岗位 职等信息
            fillAllUserOrgInfo(records, true);
            fillFormDataRoster(records, true);
            Map<String, FtbPersonnelsTurnoverManagement> managementMap = new HashMap<>();
            List<String> userIds = records
                    .stream()
                    .filter(item -> "305".equals(item.getWorkerStatus()))
                    .map(FtbPersonnelsStaffRosterDto::getUserId)
                    .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(userIds)) {
                LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaed = Wrappers.lambdaQuery();
                lambdaed.in(FtbPersonnelsTurnoverManagement::getUserId, userIds);
                List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(lambdaed);
                managementMap = managements.stream().collect(Collectors.toMap(FtbPersonnelsTurnoverManagement::getUserId, Function.identity(), (v1, v2) -> v1));
            }
            Map<String, FtbPersonnelsTurnoverManagement> finalManagementMap = managementMap;
            records.forEach(item -> {
                if ("305".equals(item.getWorkerStatus()) && finalManagementMap.containsKey(item.getUserId())) {
                    FtbPersonnelsTurnoverManagement management = finalManagementMap.get(item.getUserId());
                    String organizationInfo = management.getOrganizationInfo();
                    List<WorkerGroupDataDto> dataDos = JSONObject.parseArray(organizationInfo, WorkerGroupDataDto.class);
                    item.setOrgList(dataDos);
                }
            });
        }

        //构建分页返回数据
        return CultivatePage.coverPageInfo(page);
    }
    @Override
    public List<FtbPersonnelsStaffRosterDto> queryWithUserIdsPost(StaffRosterReq  req) {
        List<String> userSubQueryList = new ArrayList<>();
        if (CollUtil.isNotEmpty(req.getUserIds())) {
            userSubQueryList.addAll(req.getUserIds());
         }

        if (CollUtil.isNotEmpty(req.getOrgIds())) {
            QueryPageUserDTO dto = new QueryPageUserDTO();
            dto.setOrganizeIds(req.getOrgIds());
            dto.setIsPage(false);
            ActionResult<PageListVO<UserBoundVO>> listByLevel = v2UserApi.pagePost(dto);
            List<String> list = new ArrayList<>();
            List<String> userIds = listByLevel.getCode() == 200 ?
                    listByLevel.getData().getList().stream().map(UserBoundVO::getId).collect(Collectors.toList())
                    : new ArrayList<>();
            List<String> userIdsTur = doEmployeesOfYourOrganizationTur(req.getOrgIds(), null);
            if (CollUtil.isNotEmpty(userIdsTur)){
                list.addAll(userIdsTur);
            }
            if (CollUtil.isNotEmpty(userIds)){
                list.addAll(userIds);
            }
            // 判断组织中是否包含查询人员
            if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(userSubQueryList)) {
                userSubQueryList = list.stream().filter(userSubQueryList::contains).collect(Collectors.toList());
            }else {
                userSubQueryList = list;
            }
        }
        if (CollUtil.isEmpty(userSubQueryList)) return new ArrayList<>();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = Wrappers.lambdaQuery();
        wrapper.in(CollUtil.isNotEmpty(userSubQueryList),FtbPersonnelsStaffRoster::getUserId, userSubQueryList.stream().distinct().collect(Collectors.toList()));
        wrapper.like(StringUtils.isNotBlank(req.getKeyWords()) ,FtbPersonnelsStaffRoster::getName, req.getKeyWords());
        List<FtbPersonnelsStaffRoster> personnelsStaffRosters = baseMapper.selectList(wrapper);
        if (CollUtil.isEmpty(personnelsStaffRosters)) return new ArrayList<>();
        List<FtbPersonnelsStaffRosterDto> staffRosterDtos = personnelsStaffRosters.stream().map(FtbPersonnelsStaffRosterDto::changeEscape).collect(Collectors.toList());
        fillAllUserOrgInfo(staffRosterDtos, true);
        //fillFormDataRoster(staffRosterDtos, true);
        Map<String, FtbPersonnelsTurnoverManagement> managementMap = new HashMap<>();
        List<String> userIds = staffRosterDtos
                .stream()
                .filter(item -> "305".equals(item.getWorkerStatus()))
                .map(FtbPersonnelsStaffRosterDto::getUserId)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userIds)) {
            LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaed = Wrappers.lambdaQuery();
            lambdaed.in(FtbPersonnelsTurnoverManagement::getUserId, userIds);
            List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(lambdaed);
            managementMap = managements.stream().collect(Collectors.toMap(FtbPersonnelsTurnoverManagement::getUserId, Function.identity(), (v1, v2) -> v1));
        }
        Map<String, FtbPersonnelsTurnoverManagement> finalManagementMap = managementMap;
        staffRosterDtos.forEach(item -> {
            if ("305".equals(item.getWorkerStatus()) && finalManagementMap.containsKey(item.getUserId())) {
                FtbPersonnelsTurnoverManagement management = finalManagementMap.get(item.getUserId());
                String organizationInfo = management.getOrganizationInfo();
                List<WorkerGroupDataDto> dataDos = JSONObject.parseArray(organizationInfo, WorkerGroupDataDto.class);
                item.setOrgList(dataDos);
            }
        });
        return staffRosterDtos;
    }

    @Override
    public List<FtbPersonnelsStaffRosterDto> postWithSalaryNoPage(StaffRosterListReq req) {
        //薪酬的筛选单独处理
        //查询用户数据权限
        List<String> userList = new ArrayList<>();
        String isQueryAuth = req.getIsQueryAuth();
        if (CollUtil.isNotEmpty(req.getUserIds())) {
            userList = req.getUserIds();
        }
        if (!"0".equals(isQueryAuth)) {
            if (!UserProvider.getUser().getIsAdministrator()) {
                List<String> authUserList = queryCacheAuthUserList(req.getModuleCode(), req.getCategory());
                if (CollectionUtil.isNotEmpty(authUserList)) {
                    List<String> finalUserList = userList;
                    // 筛选出当前用户权限下的用户
                    userList = authUserList.stream().filter(v -> {
                        if (CollUtil.isEmpty(finalUserList)) return true;
                        if (finalUserList.contains(v)) {
                            return true;
                        } else {
                            return false;
                        }
                    }).collect(Collectors.toList());
                    if (CollUtil.isEmpty(userList)) {
                        return new ArrayList<>();
                    }
                }
            }
            String targetOrganizeId = req.getTargetOrganizeId();
            String targetPositionId = req.getTargetPositionId();
            if (StringUtils.isNotEmpty(targetOrganizeId)) {
                QueryPageUserDTO dto = new QueryPageUserDTO();
                dto.setOrganizeIds(List.of(targetOrganizeId.split(",")));
                dto.setIsPage(false);
                dto.setPositionId(targetPositionId);
                ActionResult<PageListVO<UserBoundVO>> listByLevel = v2UserApi.pagePost(dto);
                List<String> userSubQueryList = listByLevel.getCode() == 200 ?
                        listByLevel.getData().getList().stream().map(UserBoundVO::getId).collect(Collectors.toList())
                        : new ArrayList<>();
                if (CollectionUtil.isEmpty(userList)) {
                    if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                        userList = userSubQueryList;
                    } else {
                        return new ArrayList<>();
                    }
                } else {
                    if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                        userList = userList.stream()
                                .filter(userSubQueryList::contains)
                                .collect(Collectors.toList());
                        if (CollectionUtil.isEmpty(userList)) {
                            return new ArrayList<>();
                        }
                    } else {
                        return new ArrayList<>();
                    }
                }
            }
            List<String> orgIds = null;
            List<String> turUserIds = null;
            List<String> filteOrgIds = StringUtils.isNotEmpty(targetOrganizeId) ? Arrays.asList(targetOrganizeId.split(",")) : null;
            if (!UserProvider.getUser().getIsAdministrator()) {
                // 数据权限userIds
                orgIds = permissionsUtils.obtainPersonnelOrganizationIdDataPermissions(UserProvider.getUser().getUserId(), req.getModuleCode(), req.getCategory());
                PermissionsApplicableObject permissionsApplicableObject = permissionsUtils.obtainTheScopeOfUserPermissionsEnums(UserProvider.getUser().getUserId());
                // 数据权限 仅下属单独处理
                if (permissionsApplicableObject.getPermissionsApplicableEnums() == PermissionsApplicableEnums.SCOPE_SUBORDINATE) {
                    // 查询当前登录人的下属
                    turUserIds = inquireAboutSubordinates(UserProvider.getUser().getUserId());
                } else {
                    if (orgIds != null) {
                        turUserIds = doEmployeesOfYourOrganizationTur(orgIds, targetPositionId);
                    }
                }
            }
            if (filteOrgIds != null || StrUtil.isNotBlank(targetPositionId)) {
                if (CollUtil.isNotEmpty(filteOrgIds) && CollUtil.isNotEmpty(orgIds)) {
                    assert orgIds != null;
                    orgIds = orgIds.stream().filter(filteOrgIds::contains).collect(Collectors.toList());
                } else if (CollUtil.isNotEmpty(filteOrgIds) && orgIds == null) {
                    orgIds = filteOrgIds;
                }
                turUserIds = doEmployeesOfYourOrganizationTur(orgIds, targetPositionId);
            }
            if (CollUtil.isNotEmpty(turUserIds)) {
                if ("-1".equals(turUserIds.get(0))) {
                    //组织/岗位筛选无数据
                    userList = turUserIds;
                } else {
                    if (!UserProvider.getUser().getIsAdministrator() && (StrUtil.isNotBlank(targetPositionId) || StrUtil.isNotBlank(targetOrganizeId))) {
                        Collection<String> intersection = CollectionUtil.intersection(userList, turUserIds);
                        // 离职人员
                        Collection<String> subtract = CollectionUtil.subtract(turUserIds, userList);
                        // 合并交集与差集
                        List<String> mergedList = new ArrayList<>(intersection);
                        mergedList.addAll(subtract);
                        userList = mergedList;
                        if (CollectionUtil.isEmpty(userList)) {
                            userList.add("-1");
                        }
                    } else {
                        userList.addAll(turUserIds);
                    }
                }
            }
        }
        List<FtbPersonnelsStaffRosterDto> records = baseMapper.queryNewWithTurnoverManagerList(req, userList);
        if (CollectionUtil.isNotEmpty(records)) {
            //补充组织 岗位 职等 信息 列表不在查询入职的组织岗位 职等信息
            fillAllUserOrgInfo(records, true);
            fillFormDataRoster(records, true);
            Map<String, FtbPersonnelsTurnoverManagement> managementMap = new HashMap<>();
            List<String> userIds = records
                    .stream()
                    .filter(item -> "305".equals(item.getWorkerStatus()))
                    .map(FtbPersonnelsStaffRosterDto::getUserId)
                    .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(userIds)) {
                LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaed = Wrappers.lambdaQuery();
                lambdaed.in(FtbPersonnelsTurnoverManagement::getUserId, userIds);
                List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(lambdaed);
                managementMap = managements
                        .stream()
                        .collect(Collectors.toMap(FtbPersonnelsTurnoverManagement::getUserId, Function.identity(), (v1, v2) -> v1));
            }
            Map<String, FtbPersonnelsTurnoverManagement> finalManagementMap = managementMap;
            records.forEach(item -> {
                if ("305".equals(item.getWorkerStatus()) && finalManagementMap.containsKey(item.getUserId())) {
                    FtbPersonnelsTurnoverManagement management = finalManagementMap.get(item.getUserId());
                    String organizationInfo = management.getOrganizationInfo();
                    List<WorkerGroupDataDto> dataDos = JSONObject.parseArray(organizationInfo, WorkerGroupDataDto.class);
                    item.setOrgList(dataDos);
                }
            });
        }
        return records;
    }

    /**
     * 获取花名册用户-无权限
     * @param req
     * @return
     */
    @Override
    public List<FtbPersonnelsStaffRosterDto> getPersonnelUserList(StaffRosterListReq req) {
        if (ObjectUtil.isNull(req.getCurrentPage())) {
            req.setCurrentPage(1);
            req.setPageSize(1000);
        }
        Page<FtbPersonnelsStaffRosterDto> page = new Page();
        page.setSize(req.getPageSize());
        page.setCurrent(req.getCurrentPage());
        Page<FtbPersonnelsStaffRosterDto> ftbPersonnelsStaffRosterDtoPage = baseMapper.pagingQueryNewWithTurnoverManagerList(req, req.getUserIds(), page);
        return ftbPersonnelsStaffRosterDtoPage.getRecords();
    }
    /**
     * 查询下属的离职id
     * @param userId
     * @return
     */
    public List<String> inquireAboutSubordinates(String userId){
        LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsTurnoverManagement::getEnableMark ,0);
        List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(wrapper);
        return managements.stream().filter(v -> {
            String organizationInfo = v.getOrganizationInfo();
            List<WorkerGroupDataDto> dataDto = JSONArray.parseArray(organizationInfo, WorkerGroupDataDto.class);
            if (CollUtil.isEmpty(dataDto)) {
                return false;
            }
            long count = dataDto.stream().filter(data -> data.getIsDefault() && userId.equals(data.getReportsTo())).count();
            return count > 0;
        }).map(FtbPersonnelsTurnoverManagement::getUserId).collect(Collectors.toList());
    }

    private List<String> doEmployeesOfYourOrganizationTur(List<String> orgIds, String targetPositionId) {

        List<String> personnelsStaffRosterUserIdList = new ArrayList<>();
        if (StrUtil.isNotBlank(targetPositionId)) {
            QueryUserBatchDTO queryUserBatchDTO = new QueryUserBatchDTO();
            queryUserBatchDTO.setTenantId(UserProvider.getUser().getTenantId());
            queryUserBatchDTO.setPositionIds(List.of(targetPositionId));
            ActionResult<List<UserBoundVO>> userInfoBatch = v2UserApi.getUserInfoBatch(queryUserBatchDTO);
            List<UserBoundVO> userBoundVOList = userInfoBatch.getData();
            personnelsStaffRosterUserIdList = userBoundVOList.stream().map(UserBoundVO::getId).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(personnelsStaffRosterUserIdList)) {
                personnelsStaffRosterUserIdList.add("-1");
            }
        }
        if (CollectionUtil.isNotEmpty(orgIds)) {
            ActionResult<List<UserPageListVO>> listActionResult = v2UserApi.listTargetOrganizes(orgIds, UserProvider.getUser().getTenantId(),null);
            List<String> userIds = listActionResult.getData().stream().map(UserPageListVO::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(personnelsStaffRosterUserIdList)) {
                //取交集
                Collection<String> intersection = CollectionUtil.intersection(personnelsStaffRosterUserIdList, userIds);
                personnelsStaffRosterUserIdList = new ArrayList<>(intersection);
            }else {
                personnelsStaffRosterUserIdList = userIds;
            }
        }
        if (CollUtil.isNotEmpty(orgIds) || StrUtil.isNotBlank(targetPositionId)){
            LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(FtbPersonnelsTurnoverManagement::getEnableMark ,0);
            List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(wrapper);
            if (CollUtil.isNotEmpty(orgIds)  && StringUtils.isEmpty(targetPositionId)) {
                List<String> managerUserIds = managements.stream().filter(vo -> com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(vo.getOrganizationInfo()))
                        .filter(vo -> CollUtil.isNotEmpty(JSONObject.parseArray(vo.getOrganizationInfo(), WorkerGroupDataDto.class)
                                .stream().map(WorkerGroupDataDto::getAffiliatedOrg).collect(Collectors.toList()).stream().filter(orgIds::contains).collect(Collectors.toList()))
                        ).map(FtbPersonnelsTurnoverManagement::getUserId).collect(Collectors.toList());
                managerUserIds.addAll(personnelsStaffRosterUserIdList);
                return managerUserIds;
            }
            if (CollUtil.isNotEmpty(orgIds) && StringUtils.isNotEmpty(targetPositionId)) {

                List<String> finalPostIds = List.of(targetPositionId);
                List<String> orgAndPostIdFilterUserIdList = managements.stream().filter(vo -> com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(vo.getOrganizationInfo()))
                        .filter(vo -> CollUtil.isNotEmpty(
                                JSONObject.parseArray(
                                                vo.getOrganizationInfo(), WorkerGroupDataDto.class)
                                        .stream().filter(po -> orgIds.contains(po.getAffiliatedOrg()) && finalPostIds.contains(po.getAffiliatedPosition())).collect(Collectors.toList()))
                        ).map(FtbPersonnelsTurnoverManagement::getUserId).collect(Collectors.toList());
                orgAndPostIdFilterUserIdList.addAll(personnelsStaffRosterUserIdList);
                return CollectionUtil.isEmpty(orgAndPostIdFilterUserIdList) ? List.of("-1") : orgAndPostIdFilterUserIdList;
            }
            if (StrUtil.isNotBlank(targetPositionId) && CollectionUtil.isEmpty(orgIds)) {
                List<String> finalPostIds = List.of(targetPositionId);
                List<String> filterPostUserIdList = managements.stream().filter(vo -> com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(vo.getOrganizationInfo()))
                        .filter(vo -> CollUtil.isNotEmpty(
                                JSONObject.parseArray(
                                                vo.getOrganizationInfo(), WorkerGroupDataDto.class)
                                        .stream().filter(po -> finalPostIds.contains(po.getAffiliatedPosition())).collect(Collectors.toList()))
                        ).map(FtbPersonnelsTurnoverManagement::getUserId).collect(Collectors.toList());
                filterPostUserIdList.addAll(personnelsStaffRosterUserIdList);
                return CollectionUtil.isEmpty(filterPostUserIdList) ? List.of("-1") : filterPostUserIdList;
            }
        }
        return null;
    }

    /**
     * 匹配出, user中存在的用户(包含已离职的用户),和已经不存在的用户,
     *
     * @param userIds 目标匹配用户集合
     * @return 匹配结果, 两个list
     */
    @Override
    public UserListMatchVO getUserListByMatch(List<String> userIds) {
        //先得到离职的用户
        List<FtbPersonnelsStaffRoster> personnelStaffRosters = this.list(Wrappers.<FtbPersonnelsStaffRoster>lambdaQuery()
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, StaffWorkerStatus.RESIGNED.getCode())
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
        );
        //有离职的用户则筛选出离职的人
        List<UserBasicWithMoreBoundVO> existingUserList = new ArrayList<>();
        //匹配到离职用户的离职的信息
        if (CollUtil.isNotEmpty(personnelStaffRosters)) {
            LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaed = Wrappers.lambdaQuery();
            lambdaed.in(FtbPersonnelsTurnoverManagement::getUserId, personnelStaffRosters.stream().map(FtbPersonnelsStaffRoster::getUserId).collect(Collectors.toList()));
            lambdaed.eq(FtbPersonnelsTurnoverManagement::getWorkingCondition, StaffWorkerStatus.RESIGNED.getCode());
            List<FtbPersonnelsTurnoverManagement> managements = turnoverManagementMapper.selectList(lambdaed);
            managements.forEach(management -> {
                        UserBasicWithMoreBoundVO boundVO = new UserBasicWithMoreBoundVO();
                        boundVO.setId(management.getUserId());
                        boundVO.setRealName(management.getUserName());
                        boundVO.setMobilePhone(management.getPhoneNumber());

                        List<UserBoundMoreInfoVO> moreInfoVOS = new ArrayList<>();
                        String organizationInfo = management.getOrganizationInfo();
                        List<WorkerGroupDataDto> dataDtos = JSONObject.parseArray(organizationInfo, WorkerGroupDataDto.class);
                        if (CollUtil.isNotEmpty(dataDtos)) {
                            dataDtos.forEach(dataDto -> {
                                UserBoundMoreInfoVO moreInfoVO = new UserBoundMoreInfoVO();
                                moreInfoVO.setOrganizeId(dataDto.getAffiliatedOrg());
                                moreInfoVO.setOrganizeEnCode(dataDto.getOrgEncode());
                                moreInfoVO.setOrganizeName(dataDto.getAffiliatedOrgName());
                                moreInfoVO.setPositionId(dataDto.getAffiliatedPosition());
                                moreInfoVO.setPositionEnCode(dataDto.getPositionEncode());
                                moreInfoVO.setPositionName(dataDto.getAffiliatedPositionName());
                                moreInfoVO.setPositionGradesId(dataDto.getAffiliatedRank());
                                moreInfoVO.setPositionGradesName(dataDto.getAffiliatedRankName());
                                moreInfoVO.setManagerId(dataDto.getReportsTo());
                                moreInfoVO.setManagerRealName(dataDto.getReportsToName());

                                moreInfoVOS.add(moreInfoVO);
                            });
                        }

                        boundVO.setMoreInfoVOS(moreInfoVOS);
                        existingUserList.add(boundVO);
                    }
            );
            //remove more ids
            userIds.removeAll(managements.stream().map(FtbPersonnelsTurnoverManagement::getUserId).distinct().collect(Collectors.toList()));
        }
        //再去匹配未离职用户
        V2UserListMatchVO v2UserListMatchVO = v2UserApi.getUserListByMatch(userIds).getData();
        UserListMatchVO userListMatchVO = new UserListMatchVO();
        userListMatchVO.setEliminatedUserIdList(v2UserListMatchVO.getEliminatedUserIdList());
        userListMatchVO.setExistingUserList(v2UserListMatchVO.getExistingUserList().stream().map(vo -> {
            UserBasicWithMoreBoundVO boundVO = new UserBasicWithMoreBoundVO();
            boundVO.setId(vo.getId());
            boundVO.setRealName(vo.getUserName());
            boundVO.setMobilePhone(vo.getPhone());
            boundVO.setHeadIcon(vo.getHeadIcon());
            boundVO.setThisOrganizeId(vo.getOrganizeId());
            List<UserBoundMoreInfoVO> moreInfoVOS = new ArrayList<>();
            UserBoundMoreInfoVO moreInfoVO = new UserBoundMoreInfoVO();
            moreInfoVO.setOrganizeId(vo.getOrganizeId());
            moreInfoVO.setOrganizeEnCode(vo.getOrganizeEnCode());
            moreInfoVO.setOrganizeName(vo.getOrganizeName());
            moreInfoVO.setPositionId(vo.getPositionId());
            moreInfoVO.setPositionEnCode(vo.getPositionEnCode());
            moreInfoVO.setPositionName(vo.getPositionName());
            moreInfoVO.setPositionGradesId(vo.getGradeId());
            moreInfoVO.setPositionGradesName(vo.getGradeName());
            moreInfoVOS.add(moreInfoVO);
            boundVO.setMoreInfoVOS(moreInfoVOS);
            return boundVO;
        }).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(existingUserList)) {
            userListMatchVO.getExistingUserList().addAll(existingUserList);
        }

        return userListMatchVO;
    }

    /**
     * 查询用户权限
     *
     * @return
     */
    private List<String> queryCacheAuthUserList(String moduleCode, String category) {
        UserInfo userInfo = UserProvider.getUser();
        if (userInfo.getIsAdministrator()) {
            return null;
        }
        if (StringUtils.isNotEmpty(moduleCode) && StringUtils.isNotEmpty(category)) {
            return permissionsUtils.obtainPersonnelUserIdDataPermissions(userInfo.getUserId(), moduleCode, category);
        }
        return permissionHandling.getUserIdsByUserId(userInfo.getUserId());
    }

    /**
     * 清除用户权限缓存
     */
    public void clearAuthUserList() {
        UserInfo userInfo = UserProvider.getUser();
        String cacheKey = "dataPermissions:" + userInfo.getTenantId() + ":" + userInfo.getUserId();
        redisTemplate.delete(cacheKey);
    }

    private Integer getRandom() {
        Random random = new Random();
        return random.nextInt(60);
    }

    /**
     * 填充用户的组织岗位职等信息
     *
     * @param records
     * @param isSelectShop
     */
    private void fillAllUserOrgInfo(List<FtbPersonnelsStaffRosterDto> records, Boolean isSelectShop) {
        if (CollectionUtil.isEmpty(records)) {
            return;
        }
        List<String> userIds = records.stream().map(FtbPersonnelsStaffRosterDto::getUserId).collect(Collectors.toList());
        Map<String, List<WorkerGroupDataDto>> map = personnelOrgUtils.getUserOrgBoundInfoForUserList(userIds, isSelectShop);
        for (FtbPersonnelsStaffRosterDto record : records) {
            List<WorkerGroupDataDto> list = map.get(record.getUserId());
            record.setOrgList(list);
            //兼容老数据
            dealCurrOrgInfo(list, record);
        }
    }

    /**
     * @param records
     * @param isNeedQueryRole 是否需要查询角色  true 需要，false不需要
     */
    public void fillFormDataRoster(List<FtbPersonnelsStaffRosterDto> records, Boolean isNeedQueryRole) {
        List<String> rosterIds = records.stream().map(FtbPersonnelsStaffRosterDto::getId).collect(Collectors.toList());
        List<FtbPersonnelsStaffRegistrationFormData> allList = registrationFormDataService.queryFormFieldValueForRosterIds(rosterIds);
        //按照rosterid分组
        Map<String, List<FtbPersonnelsStaffRegistrationFormData>> map = allList.stream().collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getRosterId));
        for (FtbPersonnelsStaffRosterDto entity : records) {
            List<FtbPersonnelsStaffRegistrationFormData> formDataList = map.get(entity.getId());
            personnelOrgUtils.fillRosterDtoData(entity, formDataList, isNeedQueryRole);
        }
    }

    private void dealCurrOrgInfo(List<WorkerGroupDataDto> list, FtbPersonnelsStaffRosterDto record) {
        if (CollectionUtil.isNotEmpty(list)) {
            UserInfo userInfo = UserProvider.getUser();
            String tenantId = userInfo.getTenantId();
//            String token = userInfo.getToken();
//            Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
            WorkerGroupDataDto workerGroupDataDto = list.get(0);
            record.setCurrOrg(workerGroupDataDto.getAffiliatedOrg());
            record.setCurrOrgName(workerGroupDataDto.getAffiliatedOrgName());
            record.setCurrPosition(workerGroupDataDto.getAffiliatedPosition());
            record.setCurrPositionName(workerGroupDataDto.getAffiliatedPositionName());
            record.setCurrRank(workerGroupDataDto.getAffiliatedRank());
            record.setCurrRankName(workerGroupDataDto.getAffiliatedRankName());
            record.setCurrReportsTo(workerGroupDataDto.getReportsTo());
            record.setCurrReportsToName(workerGroupDataDto.getReportsToName());
            if (StringUtils.isEmpty(record.getCurrOrg()) || StringUtils.isEmpty(record.getCurrPosition())) {
                //把第一个组织岗位职等作为入职的 兼容老数据
                personnelAsyncOldData.dealOldData(record, tenantId, null);
            }
        }
    }

    /**
     * app端查询花名册列表
     *
     * @param req
     * @return
     */
    @Override
    public PageInfo<FtbPersonnelsStaffRosterDto> getAppPageList(AppStaffRosterListReq req) {
        //查询用户数据权限
        List<String> userList = queryCacheAuthUserList(null, "App");
        if (userList != null && userList.isEmpty()) {
            return new PageInfo<>(new ArrayList<>());
        }
        if (CollUtil.isNotEmpty(req.getOrganizeIds())) {
            QueryPageUserDTO dto = new QueryPageUserDTO();
            dto.setOrganizeIds(req.getOrganizeIds());
            dto.setIsPage(false);
            ActionResult<PageListVO<UserBoundVO>> listByLevel = v2UserApi.pagePost(dto);
            List<String> userSubQueryList = listByLevel.getCode() == 200 ?
                    listByLevel.getData().getList().stream().map(UserBoundVO::getId).collect(Collectors.toList())
                    : new ArrayList<>();
            if (CollectionUtil.isEmpty(userList)) {
                if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                    userList = userSubQueryList;
                } else {
                    return new PageInfo<>(new ArrayList<>());
                }
            } else {
                if (CollectionUtil.isNotEmpty(userSubQueryList)) {
                    userList = userList.stream()
                            .filter(userSubQueryList::contains)
                            .collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(userList)) {
                        return new PageInfo<>(new ArrayList<>());
                    }
                } else {
                    return new PageInfo<>(new ArrayList<>());
                }
            }
        }
        // 补充生日筛选区间
        String startBirthdayTime = req.getStartBirthdayTime();
        String endBirthdayTime = req.getEndBirthdayTime();
        if (startBirthdayTime != null && endBirthdayTime != null) {
            List<String> phoneNumber = baseMapper.queryBirthday(startBirthdayTime, endBirthdayTime);
            if (CollUtil.isNotEmpty(phoneNumber)) {
                req.setPhoneNumberList(phoneNumber);
            } else {
                return new PageInfo<>(new ArrayList<>());
            }
        }
        //健康证状态
        Integer healthCertificateStatus = req.getHealthCertificateStatus();
        if(Objects.nonNull(healthCertificateStatus)){
            List<String> userIdsByStatus = certificateInstanceService.getHealthCertificateUserIdsByStatus(healthCertificateStatus);
            if(userList == null){
                userList = userIdsByStatus;
            }else{
                Set<String> userIdsByStatusSet = new HashSet<>(userIdsByStatus);
                userList.removeIf(u-> !userIdsByStatusSet.contains(u));
            }
        }
        Page<FtbPersonnelsStaffRosterDto> queryPage = baseMapper.pagingAppQuery(
                Page.of(req.getCurrentPage(), req.getPageSize()),
                req, userList);
        List<FtbPersonnelsStaffRosterDto> records = queryPage.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            //补充组织 岗位 职等 信息 推荐人、推荐门店
            //去掉入职的组织岗位职等信息的查询 因为列表不需要
//            personnelOrgUtils.fillCurrOrgName(records);
//            personnelOrgUtils.fillCurrPositionName(records);
//            personnelOrgUtils.fillCurrRankName(records);
//            personnelOrgUtils.fillReportsToInfo(records);
            fillContractTypeName(records);//补充合同类型名称
            fillAllUserOrgInfo(records, false);
        }
        List<String> userIds = records.stream().map(FtbPersonnelsStaffRosterDto::getUserId).collect(Collectors.toList());
        List<HealthCertificateDetailVO> healthCertificateDetails = certificateInstanceService.getHealthCertificateDetails(userIds);
        Map<String, HealthCertificateDetailVO> healthCertificateDetailMap = healthCertificateDetails.stream()
                .collect(Collectors.toMap(HealthCertificateDetailVO::getUserId, v -> v));
        records.forEach(item -> {
            if ("304".equals(item.getWorkerStatus())) {
                LambdaQueryWrapper<FtbPersonnelsTurnoverManagement> lambdaQuery = Wrappers.lambdaQuery();
                lambdaQuery.eq(FtbPersonnelsTurnoverManagement::getUserId, item.getUserId());
                lambdaQuery.eq(FtbPersonnelsTurnoverManagement::getEnableMark, 0);
                lambdaQuery.last("limit 1");
                FtbPersonnelsTurnoverManagement management = turnoverManagementMapper.selectOne(lambdaQuery);
                if (management != null && management.getTurnoverStatus() == 6) {
                    item.setTurnoverStatusFlag("1");
                } else {
                    item.setTurnoverStatusFlag("");
                }
            }
            // 健康证回填
            HealthCertificateDetailVO healthCertificateDetail = healthCertificateDetailMap.get(item.getUserId());
            if (healthCertificateDetail != null) {
                item.setHealthCertificateStatus(healthCertificateDetail.getStatus());
                item.setHealthCertificateId(healthCertificateDetail.getCertificateInstanceId());
            }
        });
        //构建分页返回数据
        PageInfo<FtbPersonnelsStaffRosterDto> pageInfo = new PageInfo<>();
        pageInfo.setList(records);
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setTotal((int) queryPage.getTotal());
        return pageInfo;
    }

    /**
     * 修改转正状态 记录薪酬 和 成长日志
     *
     * @param userId
     * @param dto
     * @param money
     * @param tenantId
     */
    @Override
    public void innerChangeRegular(String userId, StaffRegularDto dto, BigDecimal money, String tenantId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null == entity) {
            throw new RuntimeException("花名册用户数据不存在");
        }
        FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
        roster.setUserId(userId);
        roster.setWorkerStatus("303");
        roster.setId(entity.getId());
        if (null == dto.getRegularDate()) {
            roster.setActualProbationaryDate(new Date());
        } else {
            roster.setActualProbationaryDate(dto.getRegularDate());
        }
        roster.setCurrSalary(money);
        roster.setRegularSalary(money);
        baseMapper.updateById(roster);
        registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", "303");
        //写入薪酬
        AddSalaryChangeLogDto addSalaryChangeLogDto = new AddSalaryChangeLogDto();
        addSalaryChangeLogDto.setUserId(entity.getUserId());
        addSalaryChangeLogDto.setChangeDate(new Date());
        addSalaryChangeLogDto.setSalary(money);
        addSalaryChangeLogDto.setChangeType(SalaryChangeTypeEnum.BECOME_REGULAR_WORKER.getCode());
        salaryChangeLogService.addSalaryChangeLog(addSalaryChangeLogDto);
        //员工成长
        AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
        addGrowthLogDto.setUserId(entity.getUserId());
        addGrowthLogDto.setChangeDate(new Date());
        addGrowthLogDto.setGrowthType(GrowthLogEnum.BECOME_REGULAR_WORKER.getCode());
        addGrowthLogDto.setDetail(JSONUtil.toJsonStr(dto));
        addGrowthLogDto.setRemarks(dto.getRemarks());
        addGrowthLogDto.setEmployeeId(entity.getSystemWokerId());
        // 添加转正日期
        // 转正的
        growthLogService.addGrowthLog(addGrowthLogDto);

        List<WorkerGroupDataDto> workerGroupDataDtoList = personnelOrgUtils.getUserOrgBoundInfo(userId,tenantId);
        if (CollectionUtil.isEmpty(workerGroupDataDtoList)) {
            throw new RuntimeException("用户没有组织岗位职等");
        }
        // 2025-01-15转正要求屏蔽掉组织同步，不需要同步组织岗位职等bug编号4356
        //changeUserOrgInfo(workerGroupDataDtoList, userId, dto);
        //调整实际转正日期
        registrationFormDataService.updateForOneField(roster.getId(), entity.getPhone(), "actualProbationaryDate", personnelOrgUtils.dateToString(roster.getActualProbationaryDate(), ""));
        registrationFormDataService.updateForOneField(roster.getId(), entity.getPhone(), "confirmationRemarks", dto.getRemarks());
        //同步状态到内推池子
        personnelOrgUtils.sysWorkerStatusToUchisuike(entity.getPhone(), "303");
        //同步转正日期
        UpdateUserDTO userDTO = new UpdateUserDTO();
        userDTO.setWorkerStatus("303");
        userDTO.setTenantId(tenantId);
        userDTO.setBecomeDate(dto.getRegularDate());
        v2UserApi.updateUserInfo(entity.getUserId(),userDTO);
    }

    /**
     * 调整用户的组织岗位职等 直属主管等信息
     *
     * @param workerGroupDataDtoList
     * @param userId
     * @param dto
     */
    private void changeUserOrgInfo(List<WorkerGroupDataDto> workerGroupDataDtoList, String userId, StaffRegularDto dto) {
        for (WorkerGroupDataDto workerGroupDataDto : workerGroupDataDtoList) {
            if (workerGroupDataDto.getAffiliatedOrg().equals(dto.getNewOrg()) &&
                    workerGroupDataDto.getAffiliatedPosition().equals(dto.getNewPosition()) &&
                    workerGroupDataDto.getAffiliatedRank().equals(dto.getNewRank())
            ) {
                if (StringUtils.isNotEmpty(workerGroupDataDto.getReportsTo()) && StringUtils.isNotEmpty(dto.getImmediateSuperId())) {
                    if (workerGroupDataDto.getReportsTo().equals(dto.getImmediateSuperId())) {
                        return;
                    }
                }
            }
        }
        WorkerGroupDataDto defaultWorker = null;
        for (WorkerGroupDataDto workerGroupDataDto : workerGroupDataDtoList) {
            if (workerGroupDataDto.getIsDefault()) {
                defaultWorker = workerGroupDataDto;
                break;
            }
        }
        if (null == defaultWorker) {
            defaultWorker = workerGroupDataDtoList.get(0);
        }

        UpdateUserManagerBoundDTO updateUserManagerBoundDTO = new UpdateUserManagerBoundDTO();
        updateUserManagerBoundDTO.setUserId(userId);
        updateUserManagerBoundDTO.setOldOrgId(defaultWorker.getAffiliatedOrg());
        updateUserManagerBoundDTO.setOldPositionId(defaultWorker.getAffiliatedPosition());
        updateUserManagerBoundDTO.setOldPositionGradesId(defaultWorker.getAffiliatedRank());
        updateUserManagerBoundDTO.setOldManagerId(defaultWorker.getReportsTo());
        updateUserManagerBoundDTO.setOrgId(dto.getNewOrg());
        updateUserManagerBoundDTO.setPositionId(dto.getNewPosition());
        updateUserManagerBoundDTO.setPositionGradesId(dto.getNewRank());
        updateUserManagerBoundDTO.setManagerId(dto.getImmediateSuperId());
        personnelOrgUtils.updateSysUserBound(updateUserManagerBoundDTO);

    }

    /**
     * 内部试用试岗 直接转正
     *
     * @param entity
     * @param dto
     */
    private void innerPreTrailChangeRegular(FtbPersonnelsStaffRoster entity, StaffRegularDto dto) {

        FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
        roster.setUserId(entity.getUserId());
        roster.setWorkerStatus(StaffWorkerStatus.FULL_TIME.getCode());
        roster.setId(entity.getId());
        roster.setActualProbationaryDate(entity.getActualStartDate());
        roster.setCurrSalary(entity.getEntrySalary());
        roster.setRegularSalary(entity.getEntrySalary());
        baseMapper.updateById(roster);
        registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", StaffWorkerStatus.FULL_TIME.getCode());
        //写入薪酬
        AddSalaryChangeLogDto addSalaryChangeLogDto = new AddSalaryChangeLogDto();
        addSalaryChangeLogDto.setUserId(entity.getUserId());
        addSalaryChangeLogDto.setChangeDate(new Date());
        addSalaryChangeLogDto.setSalary(entity.getEntrySalary());
        addSalaryChangeLogDto.setChangeType(SalaryChangeTypeEnum.BECOME_REGULAR_WORKER.getCode());
        salaryChangeLogService.addSalaryChangeLog(addSalaryChangeLogDto);
        //员工成长
        //调整实际转正日期
        registrationFormDataService.updateForOneField(roster.getId(), entity.getPhone(), "actualProbationaryDate", personnelOrgUtils.dateToString(roster.getActualProbationaryDate(), ""));
        registrationFormDataService.updateForOneField(roster.getId(), entity.getPhone(), "confirmationRemarks", dto.getRemarks());
        //同步状态到内推池子
        personnelOrgUtils.sysWorkerStatusToUchisuike(entity.getPhone(), StaffWorkerStatus.FULL_TIME.getCode());
        //同步转正日期
        SaveUserManagerAddDTO saveUserManagerAddDTO = new SaveUserManagerAddDTO();
        saveUserManagerAddDTO.setUserId(roster.getUserId());
        saveUserManagerAddDTO.setBecomeDate(roster.getActualProbationaryDate());
        personnelOrgUtils.sysTenantAccountBase(saveUserManagerAddDTO);
    }

    /**
     * 删除用户重置花名册入职次数
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public void resetWorkerNumber(List<String> userId) {
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbPersonnelsStaffRoster::getUserId, userId);
        List<FtbPersonnelsStaffRoster> list = baseMapper.selectList(queryWrapper);
        List<String> phones = list.stream().map(FtbPersonnelsStaffRoster::getPhone).collect(Collectors.toList());
        LambdaUpdateWrapper<FtbPersonnelsStaffRoster> updateWraper = Wrappers.lambdaUpdate();
        updateWraper.in(FtbPersonnelsStaffRoster::getUserId, userId);
        updateWraper.set(FtbPersonnelsStaffRoster::getJoinNum,0);
        baseMapper.update(new FtbPersonnelsStaffRoster(), updateWraper);
        LambdaQueryWrapper<FtbPersonnelsStaffRegistrationFormData> deleteWrapper = Wrappers.lambdaQuery();
        deleteWrapper.in(FtbPersonnelsStaffRegistrationFormData::getPhone, phones);
        registrationFormDataService.remove(deleteWrapper);
    }

    /**
     * 撤销转正状态
     *
     * @param userId
     */
    @Override
    public void cancelRegular(String userId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null != entity) {
            LambdaUpdateWrapper<FtbPersonnelsStaffRoster> updateWraper = new LambdaUpdateWrapper<>();
            updateWraper.set(FtbPersonnelsStaffRoster::getWorkerStatus, entity.getPreRegStatus());
            updateWraper.set(FtbPersonnelsStaffRoster::getActualProbationaryDate, null);

            entity.setRegularSalary(new BigDecimal(0));
            if (entity.getEntrySalary() == null) {
                entity.setCurrSalary(entity.getEntrySalary());
            } else {
                entity.setCurrSalary(entity.getEntrySalary());
            }

            updateWraper.eq(FtbPersonnelsStaffRoster::getId, entity.getId());
            this.update(updateWraper);

            registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", entity.getPreRegStatus());
            registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "actualProbationaryDate", "");
            registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "confirmationRemarks", "");
        }
    }

    /**
     * 修改转正前的状态（内部调用）
     *
     * @param userId 用户ID
     */
    @Override
    public void recordPreRegularStatus(String userId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null != entity) {
            FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
            roster.setUserId(userId);
            roster.setPreRegStatus(entity.getWorkerStatus());
            roster.setId(entity.getId());
            baseMapper.updateById(roster);
        }
    }


    /**
     * 撤销离职
     *
     * @param userId
     */
    @Override
    public String canceldepart(String userId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null == entity) {
            throw new RuntimeException("花名册用户数据不存在");
        }
        FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
        roster.setId(entity.getId());
        String departStatus = entity.getDepartStatus();
        roster.setWorkerStatus(departStatus);
        roster.setIsSignSeparation(0);
        baseMapper.updateById(roster);
        registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", roster.getWorkerStatus());

        return departStatus;
    }

    /**
     * 修改离职状态
     *
     * @param userId
     * @param listDto
     * @param resignationDate
     */
    @Override
    public Boolean innerChangeDepart(String userId, StaffDepartDto listDto, String remarks, Date resignationDate, String tenantId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null != entity && !entity.getWorkerStatus().equals(StaffWorkerStatus.RESIGNED.getCode())) {
            FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
            roster.setUserId(userId);
            roster.setWorkerStatus(StaffWorkerStatus.RESIGNED.getCode());
            roster.setId(entity.getId());
            //记录离职时间
            roster.setDepartDate(resignationDate);
            baseMapper.updateById(roster);
            registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", StaffWorkerStatus.RESIGNED.getCode());

            QueryWrapper<FtbPersonnelsStaffEmploymentApply> removeWrapper = new QueryWrapper<>();
            removeWrapper.lambda().eq(FtbPersonnelsStaffEmploymentApply::getPhone, entity.getPhone());
            //同步状态到内推池子
            personnelOrgUtils.sysWorkerStatusToUchisuike(entity.getPhone(), StaffWorkerStatus.RESIGNED.getCode());
            staffEmploymentApplyService.remove(removeWrapper);
            //员工成长
            AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
            addGrowthLogDto.setUserId(entity.getUserId());
            addGrowthLogDto.setChangeDate(resignationDate);
            addGrowthLogDto.setGrowthType(GrowthLogEnum.DEPART.getCode());
            addGrowthLogDto.setDetail(JSONUtil.toJsonStr(listDto));
            addGrowthLogDto.setRemarks(remarks);
            addGrowthLogDto.setEmployeeId(entity.getSystemWokerId());
            // 离职的
            growthLogService.addGrowthLog(addGrowthLogDto);

            //同步离职日期
            SaveUserManagerAddDTO saveUserManagerAddDTO = new SaveUserManagerAddDTO();
            saveUserManagerAddDTO.setUserId(roster.getUserId());
            saveUserManagerAddDTO.setDepartDate(resignationDate);
            personnelOrgUtils.sysTenantAccountBase(saveUserManagerAddDTO);

            //TODO 历史数据兼容问题重置
//            List<FormTypeDto> list = registrationFormDataService.queryArchivalForm(userId, tenantId);
//            list = removeOptionData(list);
//            log.error("离职timing={}", userId);
//            FtbPersonnelsStaffArchivesHistory history = new FtbPersonnelsStaffArchivesHistory();
//            history.setUserId(userId);
//            history.setArchives(JSONUtil.toJsonStr(list));
//            history.setEnabledMark(1);
//            history.setCreatorTime(new Date());
//            ftbPersonnelsStaffArchivesHistoryService.save(history);
//            //离职清除老数据
//            QueryWrapper<FtbPersonnelsStaffRegistrationFormData> formDataUpdateWrapper = new QueryWrapper<>();
//            formDataUpdateWrapper.lambda().eq(FtbPersonnelsStaffRegistrationFormData::getRosterId, entity.getId());
//            registrationFormDataService.remove(formDataUpdateWrapper);

        }
        return true;

    }


    /**
     * 去除字段选项
     * @param list
     * @return
     */
    private List<FormTypeDto> removeOptionData(List<FormTypeDto> list) {
        if(CollUtil.isEmpty(list)){
            return list;
        }
        for (FormTypeDto formTypeDto : list) {
            List<GroupFieldDataDto> groupFieldDataDtoList = formTypeDto.getGroupFieldDataDtoList();
            if(CollUtil.isEmpty(groupFieldDataDtoList)){
                continue;
            }
            for (GroupFieldDataDto groupFieldDataDto : groupFieldDataDtoList){
                FormFieldDto formFieldDto = groupFieldDataDto.getFormFieldDto();
                if(formFieldDto==null){
                    continue;
                }
                formFieldDto.setOptionDtoList(Collections.EMPTY_LIST);
            }
        }
        return list;
    }


    /**
     * 内部调用 用户晋升
     *
     * @param userId 用户ID
     * @param dto
     * @param money  金额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void innerPromotion(String userId, StaffPromotionDto dto, BigDecimal money) {
        log.error("晋升={},userid={},money={}", userId, dto, money);
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null == entity) {
            throw new RuntimeException("花名册用户数据不存在");
        }
        FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
        roster.setUserId(userId);
        roster.setId(entity.getId());
        roster.setCurrSalary(money);
        baseMapper.updateById(roster);


        //写入薪酬
        AddSalaryChangeLogDto addSalaryChangeLogDto = new AddSalaryChangeLogDto();
        addSalaryChangeLogDto.setUserId(entity.getUserId());
        addSalaryChangeLogDto.setChangeDate(new Date());
        addSalaryChangeLogDto.setSalary(money);
        addSalaryChangeLogDto.setChangeType(SalaryChangeTypeEnum.promotion.getCode());
        salaryChangeLogService.addSalaryChangeLog(addSalaryChangeLogDto);
        //员工成长
        AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
        addGrowthLogDto.setUserId(entity.getUserId());
        addGrowthLogDto.setChangeDate(new Date());
        addGrowthLogDto.setGrowthType(GrowthLogEnum.promotion.getCode());

        addGrowthLogDto.setDetail(JSONUtil.toJsonStr(dto));
        addGrowthLogDto.setEmployeeId(entity.getSystemWokerId());
        // 晋升的
        growthLogService.addGrowthLog(addGrowthLogDto);

    }

    /**
     * 内部调用 修改 待离职 状态
     *
     * @param userId 用户ID
     */
    @Override
    public void innerChangeWaitDepart(String userId, String taskInfoId, Integer version) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null != entity) {
            FtbPersonnelsStaffRoster roster = new FtbPersonnelsStaffRoster();
            roster.setUserId(userId);
            roster.setDepartStatus(entity.getWorkerStatus());
            roster.setWorkerStatus("304");
            roster.setId(entity.getId());
            roster.setTaskInfoId(taskInfoId);
            roster.setVersionNum(version);
            baseMapper.updateById(roster);
            registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "workerStatus", "304");
        }
    }

    /**
     * 根据用户ID查询用户的基本信息
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public String querySystemWorkerId(String userId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        if (null != entity) {
            return entity.getSystemWokerId();
        }
        return "";
    }


    /**
     * 检查手机号是否存在花名册中
     *
     * @param phone 手机号吗
     * @return
     */
    @Override
    public Boolean checkPhoneExistForRoster(String phone) {
        FtbPersonnelsStaffRoster oldRoster = queryRosterInfoByPhone(phone);
        if (null == oldRoster) {
            return false;
        }
        if (oldRoster.getEnabledMark().equals(1)) {
            return false;
        }
        //重复入职
        if (oldRoster.getWorkerStatus().equals("305")) {
            return false;
        }
        return true;
    }

    /**
     * 填充合同名称
     *
     * @param records
     */

    private void fillContractTypeName(List<FtbPersonnelsStaffRosterDto> records) {
        //获取合同类型ids
        List<String> contractTypeIds = new ArrayList<>();
        for (FtbPersonnelsStaffRosterDto record : records) {

            if (StringUtils.isNotEmpty(record.getContractTypeName())) {
                continue;
            }
            if (StringUtils.isNotEmpty(record.getContractType())) {
                contractTypeIds.add(record.getContractType());
            }
        }
        if (CollectionUtil.isEmpty(contractTypeIds)) {
            return;
        }
        List<ContractTypeVO> contractTypeVOS = personnelOrgUtils.queryContractTypeForIds(contractTypeIds);
        if (CollectionUtil.isEmpty(contractTypeVOS)) {
            return;
        }
        Map<String, String> contractTypeMap = contractTypeVOS.stream().collect(Collectors.toMap(ContractTypeVO::getId, ContractTypeVO::getFullName));

        for (FtbPersonnelsStaffRosterDto record : records) {
            if (StringUtils.isNotEmpty(record.getContractType()) && StringUtils.isEmpty(record.getContractTypeName())) {
                record.setContractTypeName(contractTypeMap.get(record.getContractType()));
            }
        }
    }

    /**
     * 查询检查花名册数据是否存在
     *
     * @param id 花名册id
     * @return
     */
    private FtbPersonnelsStaffRoster queryRosterAndCheckById(String id) {
        FtbPersonnelsStaffRoster entity = baseMapper.selectById(id);
        if (null == entity) {
            throw new RuntimeException("数据不存在");
        }
        if (entity.getEnabledMark().equals(1)) {
            throw new RuntimeException("数据已经删除");
        }
        return entity;
    }


    /**
     * 根据花名册id批量删除
     *
     * @param ids 主键集合
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteBatchData(List<String> ids) {
        long totalStart = System.currentTimeMillis();
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectBatchIds(ids);
        if (CollectionUtil.isEmpty(rosterList)) {
            throw new RuntimeException("数据不存在");
        }
        List<FtbPersonnelsStaffRoster> deleteList = new ArrayList<>();
        for (FtbPersonnelsStaffRoster roster : rosterList) {
//            if ("304".equals(roster.getWorkerStatus())) {
//                throw new RuntimeException(roster.getName() + "员工处于离职流程中，不可办理其他业务");
//            }
            if (roster.getEnabledMark().equals(0)) {
                deleteList.add(roster);
            }
        }
        if (CollectionUtil.isEmpty(deleteList)) {
            return;
        }
        long filterEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 过滤可删除数据 条数={} 耗时={}ms",
                deleteList.size(), filterEnd - totalStart);
        // 逻辑删除
        long logicStart = System.currentTimeMillis();
        LambdaUpdateWrapper<FtbPersonnelsStaffRoster> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(FtbPersonnelsStaffRoster::getEnabledMark, 1);
        updateWrapper.set(FtbPersonnelsStaffRoster::getJoinNum,0);
        updateWrapper.in(FtbPersonnelsStaffRoster::getId, ids);
        baseMapper.update(new FtbPersonnelsStaffRoster(), updateWrapper);
        long logicEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 花名册逻辑删除 条数={} 耗时={}ms",
                ids.size(), logicEnd - logicStart);
        String tenantId = UserProvider.getUser().getTenantId();
        long asyncStart = System.currentTimeMillis();
        for (FtbPersonnelsStaffRoster roster : deleteList) {
            asyncDeleteRosterOtherData(roster);
        }
        long asyncEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 异步删除其他数据+踢人 总耗时={}ms", asyncEnd - asyncStart);
        // 删除人员信息通知培训
        List<String> userIdList = deleteList.stream().map(FtbPersonnelsStaffRoster::getUserId).collect(Collectors.toList());
        // 删除角色权限
        long permStart = System.currentTimeMillis();
        ftbPermissionRoleAuthorizePersonService.deleteEmployeeAllPermission(userIdList);
        long permEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 删除角色权限(deleteEmployeeAllPermission) 条数={} 耗时={}ms",
                userIdList.size(), permEnd - permStart);
        // 删除租户服务信息
        long tenantDelStart = System.currentTimeMillis();
        pTenantAccountApi.deleteUsers(userIdList);
        long tenantDelEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 调用PTenantAccountApi.deleteUsers 条数={} 耗时={}ms",
                userIdList.size(), tenantDelEnd - tenantDelStart);
        long permUserDelStart = System.currentTimeMillis();
        v2UserApi.removeUsers(userIdList,null);
        long permUserDelEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 调用V2UserApi.removeUsers 条数={} 耗时={}ms",
                userIdList.size(), permUserDelEnd - permUserDelStart);
        RTopic theCompany_topic = redissonClient.getTopic("leavingTheCompany_topic");
        JSONObject args = new JSONObject();
        args.put("userIdList", userIdList);
        args.put("tenantId", tenantId);
        long topicStart = System.currentTimeMillis();
        theCompany_topic.publish(args.toJSONString());
        long topicEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 发布Redisson离职主题消息 耗时={}ms", topicEnd - topicStart);
        long totalEnd = System.currentTimeMillis();
        log.error("花名册批量删除(deleteBatchData) 总体耗时={}ms", totalEnd - totalStart);
    }

    /**
     * 异步删除花名册相关数据
     *
     * @param roster
     */
    private void asyncDeleteRosterOtherData(FtbPersonnelsStaffRoster roster) {
        String tenantId = personnelOrgUtils.getTenantId();
        Map<String, String> headers = personnelOrgUtils.getHeadersForLogin();
        personnelAsyncServiceUtils.asyncDeleteRosterOtherData(roster, tenantId, headers);

    }

    /**
     * 生成系统员工ID
     *
     * @return
     */
    private String generateSystemWorkerId() {
        return SelfGrowthUtil.providePersonnelsCustomIDBasedOnTheModule(SelfrowingEnum.STAFF_ROSTER);
//        int currNum = 0;
//        int max = 30;
//        while (true) {
//            String workerId = SelfGrowthUtil.providePersonnelsCustomIDBasedOnTheModule(SelfrowingEnum.STAFF_ROSTER);
//            QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
//            wrapper.lambda()
//                    .eq(FtbPersonnelsStaffRoster::getSystemWokerId, workerId);
//            Long count = baseMapper.selectCount(wrapper);
//            if (null != count && count > 0) {
//                currNum++;
//                if (currNum > max) {
//                    throw new RuntimeException("系统员工ID生成失败," + workerId);
//                } else {
//                    continue;
//                }
//            }
//            return workerId;
//        }
    }

    /**
     * 确认到岗
     *
     * @param req
     * @return
     */
    @Override
    @GlobalTransactional
    public String confirmOnDuty(ConfirmOnDutyReq req) {
        String tenantId = personnelOrgUtils.getTenantId();
        Map<String, String> headers = personnelOrgUtils.getHeadersForLogin();
        Date now = new Date();

        checkReportsTo(req.getCurrReportsTo());
        checkInputParam(req);
        if (req.getEntrySalary() == null) {
            req.setEntrySalary(BigDecimal.ZERO);
        }
        String employmentId = req.getEmploymentId();
        FtbPersonnelsStaffRoster entity = BeanUtil.copyProperties(req, FtbPersonnelsStaffRoster.class);

        //查询入职信息
        FtbPersonnelsStaffEmploymentApply employmentApply = staffEmploymentApplyService.queryAndCheckStaffEmploymentApply(employmentId);
        if (employmentApply.getEntryMoney() == null) {
            entity.setEntrySalary(new BigDecimal(0));
        } else {
            entity.setEntrySalary(employmentApply.getEntryMoney());
        }
        // 入职更新
        LambdaUpdateWrapper<FtbPersonnelsStaffEmploymentApply> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(FtbPersonnelsStaffEmploymentApply::getId, employmentId);
        updateWrapper.set(FtbPersonnelsStaffEmploymentApply::getStatus, 1);
        boolean update = staffEmploymentApplyService.update(updateWrapper);
        log.info("确认到岗:" + employmentApply.getOpUserName() + "确认到岗, 更新入职表状态返回值:" + update);

        // 签名信息迁移至花名册
        entity.setRegisterImg(employmentApply.getRegisterImg());
        //查询花名册中是否已经有数据
        UserInfoVO userInfoVO = personnelOrgUtils.queryTenantAccount("", entity.getPhone());
        FtbPersonnelsStaffRoster oldRoster = queryRosterInfoByPhone(employmentApply.getPhone());
        String updateType = SalaryApplyTypeEnum.ONBOARDING.getValue().toString();
        if (null != oldRoster) {
            //重复入职
            if (oldRoster.getEnabledMark().equals(0)) {
                if (oldRoster.getWorkerStatus().equals("302") || oldRoster.getWorkerStatus().equals("303")) {
                    throw new RuntimeException("该员工已经到岗，请勿重复操作");
                }

                if (oldRoster.getWorkerStatus().equals("304")) {
                    throw new RuntimeException("该员工已经在离职中");
                }
            }
            entity.setUserId(oldRoster.getUserId());
            entity.setId(oldRoster.getId());
            if (null != oldRoster.getJoinNum()) {
                entity.setJoinNum(oldRoster.getJoinNum() + 1);
            } else {
                entity.setJoinNum(1);
            }
            entity.setSystemWokerId(generateSystemWorkerId());
            updateType = SalaryApplyTypeEnum.DUPLICATE_ONBOARDING.getValue().toString();
        } else {
            //第一次入职
            entity.setJoinNum(1);
            //生成员工ID
            entity.setSystemWokerId(generateSystemWorkerId());
            if (null != userInfoVO && StringUtils.isNotEmpty(userInfoVO.getId())) {
                oldRoster = queryRosterInfoByUserId(userInfoVO.getId());
                if (null != oldRoster) {
                    entity.setUserId(oldRoster.getUserId());
                    entity.setId(oldRoster.getId());
                    if (null != oldRoster.getJoinNum()) {
                        entity.setJoinNum(oldRoster.getJoinNum() + 1);
                    } else {
                        entity.setJoinNum(1);
                    }
                    updateType = SalaryApplyTypeEnum.DUPLICATE_ONBOARDING.getValue().toString();
                }
            }

        }

        if (StringUtils.isNotEmpty(entity.getWorkerNo())) {
            List<FtbPersonnelsStaffRoster> rosterList = queryRosterInfoByWorkerId(entity.getWorkerNo());
            if (CollectionUtil.isNotEmpty(rosterList)) {
                if (rosterList.size() > 1) {
                    throw new RuntimeException("员工工号已经存在");
                }
                FtbPersonnelsStaffRoster workerRoster = rosterList.get(0);
                if (null != entity.getId()) {
                    if (!workerRoster.getId().equals(entity.getId())) {
                        throw new RuntimeException("员工工号已经存在");
                    }
                } else {
                    throw new RuntimeException("员工工号已经存在");
                }
            }
        }
        entity.setCurrSalary(entity.getEntrySalary());
        //100、无试用期  101、1个月内  102、1个月
        if (req.getProbationPeriod().equals("100")) {
            entity.setRegularSalary(entity.getEntrySalary());
            entity.setActualProbationaryDate(req.getActualStartDate());
        }
        //写入数据库
        entity.setEnabledMark(0);
        entity.setIsSubmitForm(employmentApply.getIsSubmitForm());
        entity.setPhone(employmentApply.getPhone());
        entity.setName(employmentApply.getWorkerName());
        entity.setCreatorTime(new Date());
        fillTrialInfo(entity, req);//填充试岗信息
        entity.setContractStatus(FContractSignStatus.NOT_INITIATED.getCode());
        entity.setContractTypeName("");
        entity.setContractType("");
        entity.setIsTrialFail(0);
        entity.setTrialFail("");
        entity.setIsSignSeparation(0);
        saveOrUpdate(entity);
        //已经填写了入职登记表，那么就要把之前入职登记表中的数据加上花名册ID
        registrationFormDataService.addRosterIdToFormData(entity.getPhone(), entity.getId());
        //同步数据到formData
        Map<String, Object> formDataMap = BeanUtil.beanToMap(req);
        Map<String, Object> formDataMapEntity = BeanUtil.beanToMap(entity);
        formDataMap.putAll(formDataMapEntity);
        formDataMap.put("planProbationaryDate", personnelOrgUtils.dateToString(req.getPlanProbationaryDate(), ""));
        formDataMap.put("actualStartDate", personnelOrgUtils.dateToString(req.getActualStartDate(), ""));
        ProbationPeriodDto probationPeriodDto = new ProbationPeriodDto(req.getProbationPeriod(), req.getProbationPeriodDay());
        formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
        formDataMap.put("workerName", entity.getName());
        if (now.after(entity.getActualStartDate())) {
            long betweenDay = DateUtil.betweenDay(entity.getActualStartDate(), new Date(), false);
            formDataMap.put("companyAge", String.valueOf(betweenDay));
        } else {
            formDataMap.put("companyAge", "0");
        }
        if (null != entity.getActualProbationaryDate()) {
            formDataMap.put("actualProbationaryDate", personnelOrgUtils.dateToString(entity.getActualProbationaryDate(), ""));
        }
        //清楚合同信息
        formDataMap.put("contractStatus", "500");
        formDataMap.put("contractCompany", "");
        formDataMap.put("contractEffectiveDate", "");
        formDataMap.put("contractName", "");
        formDataMap.put("contractType", "");
        formDataMap.put("contractFile", "");
        formDataMap.put("contractDate", "");
        formDataMap.put("contractDetail", "");
        formDataMap.put("contractTaskId", "");
        registrationFormDataService.syncData(formDataMap, entity.getPhone(), entity.getId());
        Map<String, FtbPersonnelsStaffRegistrationFormData> formMap = queryFormDataForPhone(entity.getPhone(), entity.getId());

        String currRank = entity.getCurrRank();
        String currPosition = entity.getCurrPosition();
        String currOrg = entity.getCurrOrg();
        if (null == userInfoVO || StringUtils.isEmpty(userInfoVO.getId())) {
            //生成系统租户账号
            String workerSex = personnelOrgUtils.getFormDataForField(formMap, "workerSex");
            SaveUserManagerAddDTO userManagerAddDTO = new SaveUserManagerAddDTO();
            userManagerAddDTO.setAccount(ACCOUNT_TEMP_PRE + entity.getPhone());
            userManagerAddDTO.setMobilePhone(entity.getPhone());
            userManagerAddDTO.setRealName(entity.getName());
            if (StringUtils.isEmpty(workerSex)) {
                userManagerAddDTO.setGender(3);
            } else {
                userManagerAddDTO.setGender(Integer.valueOf(workerSex));
            }
            userManagerAddDTO.setJobStatus(personnelOrgUtils.convertAccountStatus(entity.getWorkerStatus()));
            userManagerAddDTO.setOrgId(currOrg);
            userManagerAddDTO.setPositionId(currPosition);
            userManagerAddDTO.setPositionGradesId(currRank);
            userManagerAddDTO.setManagerId(entity.getCurrReportsTo());
            userManagerAddDTO.setEntryDate(entity.getActualStartDate());
            try {
                log.error("正常日志，租户账户={}", JSONUtil.toJsonStr(userManagerAddDTO));
                String userId = userApi.userManagerBoundAdd(userManagerAddDTO);
                if (StringUtils.isEmpty(userId) || userId.startsWith("{")) {
                    log.error("生成租户账号失败,dto={}，userId={}", JSONUtil.toJsonStr(userManagerAddDTO), userId);
                    throw new RuntimeException("生成账户失败");
                }
                entity.setUserId(userId);
            } catch (Exception e) {
                log.error("生成租户账号失败,dto={}", JSONUtil.toJsonStr(userManagerAddDTO), e);
                throw new RuntimeException("生成账户失败");
            }

        } else {
            //同步组织岗位职等 直属主管
            entity.setUserId(userInfoVO.getId());
            updateUserOrgAndPosition(entity.getUserId(), entity.getCurrOrg(), entity.getCurrPosition(), entity.getCurrRank(), entity.getCurrReportsTo());
        }

        //生成主账号
        UserAccountDto userAccountDto = new UserAccountDto();
        userAccountDto.setFid(entity.getUserId());
        userAccountDto.setUserName(entity.getName());
        UserInfo userInfo = UserProvider.getUser();
        userAccountDto.setTenantId(userInfo.getTenantId());
        userAccountDto.setUserMobilePhone(entity.getPhone());
        String flowerName = personnelOrgUtils.getFormDataForField(formMap, "flowerName");
        if (StringUtils.isNotEmpty(flowerName)) {
            userAccountDto.setUserNickName(flowerName);
        }

        String userHeadLog = getUserHeadLog(formMap, entity);
        userAccountDto.setHeadImageUrl(userHeadLog);

        List<UserAccountDto> addUserList = List.of(userAccountDto);
        ActionResult<List<UserAccountDto>> actionResult = null;
        long tenantAccountStart = System.currentTimeMillis();
        actionResult = pTenantAccountApi.batchAddUserAccount(addUserList);
        long tenantAccountEnd = System.currentTimeMillis();
        try {
            log.error("正常日志create main user={},result={}, PTenantAccountApi.batchAddUserAccount RT:{}ms",
                    JSONUtil.toJsonStr(userAccountDto), JSONUtil.toJsonStr(actionResult), tenantAccountEnd - tenantAccountStart);
            if (null == actionResult || !actionResult.getCode().equals(200) || CollectionUtil.isEmpty(actionResult.getData())) {
                //如果主账号生成失败就删除刚刚建立的用户
                throw new RuntimeException("主账号生成失败");
            }
        } catch (Exception e) {
            personnelOrgUtils.rollbackTenantUser(addUserList);
            throw new RuntimeException("主账号生成失败");
        }
        batchFillAccountForUserId(actionResult.getData(), tenantId, headers);
        //修改用户头像
        registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "headLogo", JSONUtil.toJsonStr(List.of(userHeadLog)));
        //修改用户的userId
        baseMapper.updateById(entity);

        //写入入职薪酬
        AddSalaryChangeLogDto addSalaryChangeLogDto = new AddSalaryChangeLogDto();
        addSalaryChangeLogDto.setUserId(entity.getUserId());
        addSalaryChangeLogDto.setChangeDate(new Date());
        addSalaryChangeLogDto.setSalary(entity.getCurrSalary());
        if (entity.getJoinNum() > 1) {
            addSalaryChangeLogDto.setChangeType(SalaryChangeTypeEnum.REPEAT_JOIN.getCode());
        } else {
            addSalaryChangeLogDto.setChangeType(SalaryChangeTypeEnum.FIRST_JOIN.getCode());
        }
        salaryChangeLogService.addSalaryChangeLog(addSalaryChangeLogDto);
        //员工成长
        AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
        addGrowthLogDto.setUserId(entity.getUserId());
        addGrowthLogDto.setChangeDate(new Date());
        if (entity.getJoinNum() > 1) {
            addGrowthLogDto.setGrowthType(GrowthLogEnum.REPEAT_JOIN.getCode());
            addGrowthLogDto.setNum(entity.getJoinNum());
        } else {
            addGrowthLogDto.setGrowthType(GrowthLogEnum.FIRST_JOIN.getCode());
        }
        addGrowthLogDto.setDetail(buildGrowthLogDetail(currOrg, currPosition, currRank, req.getCurrReportsTo(), req.getActualStartDate()));
        addGrowthLogDto.setEmployeeId(entity.getSystemWokerId());
        // 入职的
        growthLogService.addGrowthLog(addGrowthLogDto);


        //同步用户角色
        if (StringUtils.isNotEmpty(entity.getCurrRole())) {
            SynUserBoundRoleDTO synUserBoundRoleDTO = new SynUserBoundRoleDTO();
            synUserBoundRoleDTO.setUserId(entity.getUserId());
            synUserBoundRoleDTO.setRoleIds(Arrays.asList(entity.getCurrRole().split(",")));
            personnelOrgUtils.sysUserRole(synUserBoundRoleDTO);
        }
        //同步用户门店
        personnelOrgUtils.addUserStoreRelation(entity.getUserId(), req.getCurrShopId(), req.getCurrOrg(), req.getCurrPosition(), req.getCurrRank());
        //同步状态到内推池子
        personnelOrgUtils.sysWorkerStatusToUchisuike(entity.getPhone(), entity.getWorkerStatus());

        // 同步转正管理
        // 302、试用
        if (("302".equals(entity.getWorkerStatus())
                || "306".equals(entity.getWorkerStatus())) && !req.getProbationPeriod().equals("100")) {
            syncRegular(entity, req.getProbationPeriod(), req.getProbationPeriodDay(), req.getCurrReportsTo());
        }
        clearAuthUserList();

        //同步人脸
        if (StrUtil.isNotBlank(employmentApply.getPhotoFiles()) && !"[null]".equals(employmentApply.getPhotoFiles()) && !"[]".equals(employmentApply.getPhotoFiles())) {
            if (JSONUtil.isTypeJSONArray(employmentApply.getPhotoFiles())) {
                JSONUtil.toList(employmentApply.getPhotoFiles(), FtbCultivateOfflineFileDTO.class).stream().findFirst().ifPresent(
                        photo -> {
                            UserFaceDto userFaceDto = new UserFaceDto();
                            userFaceDto.setFaceData(fileApi.getTencentDownloadStringUrl(photo.getUrl()));
                            userFaceDto.setUserId(entity.getUserId());
                            attendanceUserFaceService.updateUserFace(userFaceDto);
                        }
                );
            } else {
                log.error(employmentApply.getOpUserName() + "-确认到岗, 人脸数据格式不对, 未同步人脸至考勤!");
            }
        }
        // 薪酬信息同步
        try {
            if (StrUtil.isNotBlank(employmentApply.getSalaryData()) && !"null".equals(employmentApply.getSalaryData()) && !"[]".equals(employmentApply.getSalaryData())) {
                if (JSONUtil.isTypeJSONArray(employmentApply.getSalaryData())) {
                    List<FtbPersonnelsSalaryInfo> salaryItemList = JsonUtil.getJsonToList(employmentApply.getSalaryData(), FtbPersonnelsSalaryInfo.class);
                    UserInfoWithSalary userInfoWithSalary = new UserInfoWithSalary();
                    PositionGradesInfoVO positionGradesInfoVO = personnelOrgUtils.queryRank(currRank);
                    PositionEntity positionEntity = personnelOrgUtils.queryPosition(currPosition);
                    OrganizeEntity organizeEntity = personnelOrgUtils.queryOrganizeInfo(currOrg);
                    userInfoWithSalary.setRankName(positionGradesInfoVO.getFullName());
                    userInfoWithSalary.setRankId(currRank);
                    userInfoWithSalary.setFOrgId(currOrg);
                    userInfoWithSalary.setFOrgName(organizeEntity.getFullName());
                    userInfoWithSalary.setPostId(currPosition);
                    userInfoWithSalary.setPostName(positionEntity.getFullName());
                    //生效日期取,实际 入职日期
                    if (CollUtil.isNotEmpty(salaryItemList)) {
                        personnelSalaryService.saveTheChangePayInformation(
                                salaryItemList,
                                entity.getUserId(),
                                entity.getActualStartDate(),
                                userInfoWithSalary,
                                "2",//和薪酬沟通传入固定值2
                                employmentApply.getReasonsForSalaryAdjustments(),
                                "4", 0, null, "");
                    }
                } else {
                    log.error(employmentApply.getOpUserName() + "-确认到岗, 薪酬信息数据格式不对, 未同步薪资项到考勤!");
                }
            } else {
                if (updateType.equals(SalaryApplyTypeEnum.DUPLICATE_ONBOARDING.getValue().toString())) {
                    // 暂时注释掉从新入职没有薪资  清除旧的薪资数据
//                personnelSalaryService.removeUserAllSalary(entity.getUserId());
                }
            }
        } catch (Exception e) {
            personnelOrgUtils.deleteTenantUser(entity.getUserId());
            pTenantAccountApi.deleteUser(entity.getUserId());
            throw e;
        }

        asyncDeleteHistory(List.of(entity.getUserId()));
        if (oldRoster != null) {
            asyncDeleteHistory(List.of(oldRoster.getUserId()));
        }
        // 不需要进行邀请填写
//        if (employmentApply.getIsSubmitForm() == 0) {
//            personnelAsyncServiceUtils.sendRegisterForm(entity.getUserId(), entity.getPhone(), tenantId, headers);
//        }
        personnelOrgUtils.updateBaseInfoForBaseUser(entity);
        // 最后去下发
        //同步考勤组
        String token = userInfo.getToken();
        Map<String, String> headers1 = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        threadPoolExecutor.execute(() -> {
            FeignHolder.sendFeign(headers1, () -> {
                try {
                    GroupUpdateByUserDTO groupUpdateByUserDTO = new GroupUpdateByUserDTO();
                    groupUpdateByUserDTO.setTenantId(userInfo.getTenantId());
                    groupUpdateByUserDTO.setType(1);//1入职 2离职 3调岗
                    groupUpdateByUserDTO.setToGroupId(req.getAttendanceGroup());
                    groupUpdateByUserDTO.setUserIds(List.of(entity.getUserId()));
                    groupUpdateByUserDTO.setJoiningDate(entity.getActualStartDate());
                    personnelOrgUtils.syncAttendanceGroup(groupUpdateByUserDTO);
                    log.error("确认到岗, 同步考勤信息成功!");
                    // 更新用户主岗
                    BaseUserPrimaryPositionDTO positionDTO = new BaseUserPrimaryPositionDTO();
                    positionDTO.setUserId(entity.getUserId());
                    positionDTO.setOrganizeId(entity.getCurrOrg());
                    positionDTO.setPositionId(entity.getCurrPosition());
                    positionDTO.setPositionGradesId(entity.getCurrRank());
                    positionDTO.setManagerId(entity.getCurrReportsTo());
                    userPrimaryPositionApi.updateUserPrimaryPosition(positionDTO);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return null;
            });
        });
        return entity.getId();
    }

    /**
     * 检查用户作为直属主管是否可以
     *
     * @param currReportsTo
     */
    public void checkReportsTo(String currReportsTo) {
        if (StringUtils.isEmpty(currReportsTo)) {
            return;
        }
        FtbPersonnelsStaffRoster roster = queryRosterInfoByUserId(currReportsTo);
        if (null == roster) {
            throw new RuntimeException("直属主管不存在");
        }
        if (StaffWorkerStatus.RESIGNED.getCode().equals(roster.getWorkerStatus())) {
            throw new RuntimeException("直属主管离职");
        }
        if (StaffWorkerStatus.PRE_TRIAL.getCode().equals(roster.getWorkerStatus())) {
            throw new RuntimeException("直属主管不能是试岗员工");
        }
    }

    public void asyncDeleteHistory(List<String> userIds) {
        UserInfo userInfo = UserProvider.getUser();
        String tenantId = userInfo.getTenantId();
        String token = userInfo.getToken();
        if (StringUtils.isEmpty(token)) {
            token = "";
        }
        Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        personnelAsyncServiceUtils.deleteTurnoverUserHistory(userIds, tenantId, headers);
    }

    /**
     * 异步 给任务添加新入职用户
     *
     * @param userIds
     */
    public void asyncAddNewPersonToTask(List<String> userIds,String tenantId) {
        personnelAsyncServiceUtils.asyncAddNewPersonToTask(userIds, tenantId);
    }

    private void asyncDeleteHistory(List<String> userIds, String tenantId, Map<String, String> headers) {
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        personnelAsyncServiceUtils.deleteTurnoverUserHistory(userIds, tenantId, headers);
    }

    private void fillTrialInfo(FtbPersonnelsStaffRoster entity, ConfirmOnDutyReq req) {
        TrialPeriodStatus trialPeriodStatus = TrialPeriodStatus.fromCode(req.getIsTrialJob());
        entity.setIsTrialJob(trialPeriodStatus.getCode());
        if (trialPeriodStatus == TrialPeriodStatus.YES) {
            entity.setTrialJobDay(req.getTrialJobDay());
        } else {
            entity.setTrialJobDay(0);
        }

        //
        String probationPeriod = req.getProbationPeriod();
        if (probationPeriod.equals("100")) {//无试用期
            if (trialPeriodStatus == TrialPeriodStatus.YES) {
                entity.setWorkerStatus(StaffWorkerStatus.PRE_TRIAL.getCode());
            } else {
                entity.setWorkerStatus(StaffWorkerStatus.FULL_TIME.getCode());
            }
        } else {
            if (trialPeriodStatus == TrialPeriodStatus.YES) {
                entity.setWorkerStatus(StaffWorkerStatus.PRE_TRIAL.getCode());
            } else {
                entity.setWorkerStatus(StaffWorkerStatus.TRIAL.getCode());
            }
        }
    }

    /**
     * 检查入参
     *
     * @param req
     */
    private void checkInputParam(ConfirmOnDutyReq req) {
        if (null == req.getIsTrialJob()) {
            req.setIsTrialJob(0);
        }
        String probationPeriod = req.getProbationPeriod();
        TrialPeriodStatus trialPeriodStatus = TrialPeriodStatus.fromCode(req.getIsTrialJob());
        if (probationPeriod.equals("100")) {//无试用期
            if (trialPeriodStatus == TrialPeriodStatus.YES) {
                if (req.getTrialJobDay() < 1) {
                    throw new RuntimeException("试岗天数不能小于1天");
                } else if (req.getTrialJobDay() > 999) {
                    throw new RuntimeException("试岗天数不能大于999天");
                }
            }
        } else {
            int maxDay = PersonnelStaffUtils.calculatePeriodDays(req.getProbationPeriod(), req.getProbationPeriodDay());
            if (probationPeriod.equals("101")) {//1个月内
                if (maxDay < 1) {
                    throw new RuntimeException("试用期天数不能小于1天");
                } else if (maxDay > 30) {
                    throw new RuntimeException("试用期天数不能超过1个月");
                }
            }
            if (trialPeriodStatus == TrialPeriodStatus.YES) {
                if (req.getTrialJobDay() < 1) {
                    throw new RuntimeException("试岗天数不能小于1天");
                } else if (req.getTrialJobDay() > maxDay) {
                    throw new RuntimeException("试岗天数不能大于试用天数");
                }
            }
        }
    }


    private void updateUserOrgAndPosition(String userId, String orgId, String positionId, String rankId, String reportTo) {
        WorkerGroupDataDto workerGroupDataDto = new WorkerGroupDataDto();
        workerGroupDataDto.setAffiliatedOrg(orgId);
        workerGroupDataDto.setAffiliatedPosition(positionId);
        workerGroupDataDto.setAffiliatedRank(rankId);
        workerGroupDataDto.setReportsTo(reportTo);
        personnelOrgUtils.sysUserBoundList(List.of(workerGroupDataDto), userId);
    }

    /**
     * 批量回填用户账号
     *
     * @param list
     */
    private void batchFillAccountForUserId(List<UserAccountDto> list, String tenantCode, Map<String, String> headers) {
        personnelAsyncServiceUtils.batchFillAccountForUserId(list, tenantCode, headers);
    }

    /**
     * 同步转正管理
     *
     * @param entity
     * @param probationPeriod
     * @param probationPeriodDay
     * @param currReportsTo
     */
    private void syncRegular(FtbPersonnelsStaffRoster entity,
                             String probationPeriod,
                             String probationPeriodDay,
                             String currReportsTo) {
        try {
            FtbPersonnelsRegularCreateDTO createDTO = FtbPersonnelsRegularCreateDTO.coverFtbPersonnelsRegularInfoVO(entity);
            OrganizeEntity infoById = organizeApi.getInfoById(createDTO.getOrgId());
            createDTO.setOrgName(infoById.getFullName());
            UserEntity userEntity = StringUtils.isEmpty(currReportsTo) ? null : userApi.getInfoById(currReportsTo);
            if (userEntity != null) {
                createDTO.setImmediateSuperName(userEntity.getRealName());
                createDTO.setImmediateSuperId(currReportsTo);
            }
            PositionEntity positionEntity = positionApi.queryInfoById(createDTO.getRegularPostId());
            createDTO.setRegularPostName(positionEntity.getFullName());
            createDTO.setOnboardPostName(positionEntity.getFullName());
            ActionResult<PositionGradesInfoVO> gradesInfo = positionApi.getGradesInfo(createDTO.getRegularGradeId());
            if (gradesInfo != null && gradesInfo.getData() != null) {
                createDTO.setRegularGradeName(gradesInfo.getData().getFullName());
                createDTO.setOnboardGradeName(gradesInfo.getData().getFullName());
            }
            calculatePlannedConversionTime(probationPeriod, probationPeriodDay, entity, createDTO);
            createDTO.setId(entity.getId());
            regularManagementService.applyForRegularization(createDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算计划转正时间
     *
     * @param probationPeriod    是否是天
     * @param probationPeriodDay 时间
     * @param entity
     * @param createDTO
     */
    private void calculatePlannedConversionTime(String probationPeriod,
                                                String probationPeriodDay,
                                                FtbPersonnelsStaffRoster entity,
                                                FtbPersonnelsRegularCreateDTO createDTO) {
        // 入职日期
        Date actualStartDate = entity.getActualStartDate();
        int probation = 0;
        // 创建一个 Calendar 实例并设置为当前日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(actualStartDate);
        if ("101".equals(probationPeriod)) {
            // 这里就是天数
            createDTO.setProbationPeriodDay(probationPeriodDay);
            calendar.add(Calendar.DAY_OF_MONTH, Integer.parseInt(probationPeriodDay));
        } else {
            switch (probationPeriod) {
                case "102":
                    probation = 1;
                    break;
                case "103":
                    probation = 2;
                    break;
                case "104":
                    probation = 3;
                    break;
                case "105":
                    probation = 4;
                    break;
                case "106":
                    probation = 5;
                    break;
                case "107":
                    probation = 6;
                    break;
                case "108":
                    probation = 7;
                    break;
                case "109":
                    probation = 8;
                    break;
            }
            calendar.add(Calendar.MONTH, probation);
        }
        Date time = calendar.getTime();
        createDTO.setProbation(probationPeriod);
        // 计算实际转正时间
        createDTO.setSchedConverDate(time);
    }


    public Map<String, FtbPersonnelsStaffRegistrationFormData> queryFormDataForPhone(String phone, String rosterId) {
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryFormFieldValueList(phone, rosterId);
        if (CollectionUtil.isEmpty(formDataList)) {
            return new HashMap<>();
        }
        Map<String, FtbPersonnelsStaffRegistrationFormData> map = new HashMap<>();
        for (FtbPersonnelsStaffRegistrationFormData formData : formDataList) {
            map.put(formData.getFormFieldId(), formData);
        }
        return map;
    }

    @Override
    @Transactional
    public List<ImportResultVO> addImportRosters(List<FtbRosterInsertNomalVO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return CollectionUtil.newArrayList();
        }

        if (list.size() > 200) {
            throw new RuntimeException("导入数据不能超过200条");
        }
        List<InnerImportRosterDto> innerImportDtoList = new ArrayList<>();
        //转换并检
        Map<String, FtbPersonnelsStaffRoster> rosterMap = batchQueryPhone(list);
        List<String> oldUserList = new ArrayList<>(list.size());
        List<String> oldRosterList = new ArrayList<>(list.size());

        for (FtbRosterInsertNomalVO ftbRosterInsertNomalVO : list) {
            log.info("excel import data={}", ftbRosterInsertNomalVO);
            FtbPersonnelsStaffRoster newRoster = personnelOrgUtils.buildImportRoster(ftbRosterInsertNomalVO);

            FtbPersonnelsStaffRoster oldRoster = rosterMap.get(newRoster.getPhone());
            if (null != oldRoster) {
                if (oldRoster.getWorkerStatus().equals("302") || oldRoster.getWorkerStatus().equals("303") || oldRoster.getWorkerStatus().equals("306")) {
                    ftbRosterInsertNomalVO.setIsNew(false);
                    oldUserList.add(oldRoster.getUserId());
                    oldRosterList.add(oldRoster.getId());
                }

                if (oldRoster.getWorkerStatus().equals("304")) {
                    ftbRosterInsertNomalVO.setIsNew(false);
                    oldUserList.add(oldRoster.getUserId());
                    oldRosterList.add(oldRoster.getId());
                    continue;
                }
            }
            innerImportDtoList.add(new InnerImportRosterDto(newRoster, oldRoster, ftbRosterInsertNomalVO));
        }

        Map<String, List<FtbPersonnelsStaffRegistrationFormData>> formDataValueMap = queryFormDataValueForRosterId(oldRosterList);
        UserInfo userInfo = UserProvider.getUser();
        String tenantId = userInfo.getTenantId();
        Map<String, String> headers = personnelOrgUtils.getHeadersForLogin();

        return doRealImportRoster(innerImportDtoList, tenantId, headers, userInfo, formDataValueMap);
    }

    /**
     * 批量查询用户附表数据
     *
     * @param oldRosterList
     * @return
     */
    private Map<String, List<FtbPersonnelsStaffRegistrationFormData>> queryFormDataValueForRosterId(List<String> oldRosterList) {
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryFormFieldValueForRosterIds(oldRosterList);
        if (CollectionUtil.isNotEmpty(formDataList)) {
            return formDataList.stream().collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getRosterId));
        }
        return new HashMap<>();
    }

    private Map<String, FtbPersonnelsStaffRoster> batchQueryPhone(List<FtbRosterInsertNomalVO> list) {
        Set<String> phoneSet = new HashSet<>();
        for (FtbRosterInsertNomalVO vo : list) {
            if (phoneSet.contains(vo.getPhone())) {
                throw new RuntimeException("姓名：" + vo.getUserName() + ",手机号：" + vo.getPhone() + ",手机号重复");
            }
            phoneSet.add(vo.getPhone());
        }
        List<FtbPersonnelsStaffRoster> rosterList = queryRosterInfoByPhones(new ArrayList<>(phoneSet));
        return rosterList.stream()
                .collect(Collectors.toMap(FtbPersonnelsStaffRoster::getPhone,
                        Function.identity(), (a, b) -> a));
    }

    public List<List<InnerImportRosterDto>> groupByBatch(List<InnerImportRosterDto> list, int batchSize) {
        List<List<InnerImportRosterDto>> groupedData = new ArrayList<>();
        for (int i = 0; i < list.size(); i += batchSize) {
            int end = Math.min(i + batchSize, list.size());
            groupedData.add(new ArrayList<>(list.subList(i, end)));
        }
        return groupedData;
    }

    public List<List<UserAccountDto>> groupByBatchTenant(List<UserAccountDto> list, int batchSize) {
        List<List<UserAccountDto>> groupedData = new ArrayList<>();
        for (int i = 0; i < list.size(); i += batchSize) {
            int end = Math.min(i + batchSize, list.size());
            groupedData.add(new ArrayList<>(list.subList(i, end)));
        }
        return groupedData;
    }


    private List<ImportResultVO> doRealImportRoster(List<InnerImportRosterDto> innerImportDtoList, String tenantCode,
                                                    Map<String, String> headers, UserInfo userInfo,
                                                    Map<String, List<FtbPersonnelsStaffRegistrationFormData>> formDataValueMap) {
        List<ImportResultVO> resultVOList = new ArrayList<>();
        //批量查询字段
        List<FtbPersonnelsRegistrationFormField> allFormFieldList = bachQueryField();
        //批量写入租户账号
        Map<String, String> phoneUserMap = batchWriteTenant(innerImportDtoList);
        //批量写入平台账号
        Map<String, String> userToHeadMap = batchWritePlatAccount(innerImportDtoList, phoneUserMap, userInfo);

        Map<String, FtbPersonnelsRegistrationFormField> allFormFieldListMap = allFormFieldList.stream()
                .collect(Collectors.toMap(FtbPersonnelsRegistrationFormField::getId, Function.identity()));
        //导入操作
        for (InnerImportRosterDto innerImportRosterDto : innerImportDtoList) {
            InnerImportResultVO resultVO = null;
            if (innerImportRosterDto.getFtbRosterInsertNomalVO().getIsNew()) {
                resultVO = addImportOneRoster(innerImportRosterDto.getFtbRosterInsertNomalVO(), innerImportRosterDto.getNewRoster(), innerImportRosterDto.getOldRoster(),
                        userInfo, phoneUserMap, userToHeadMap, allFormFieldListMap);
            } else {
                List<FtbPersonnelsStaffRegistrationFormData> formDataValueList = formDataValueMap.get(innerImportRosterDto.getOldRoster().getId());
                resultVO = updateImportOneRoster(innerImportRosterDto.getFtbRosterInsertNomalVO(), innerImportRosterDto.getNewRoster(), innerImportRosterDto.getOldRoster(),
                        allFormFieldList, allFormFieldListMap, formDataValueList);
            }
            resultVOList.add(new ImportResultVO(resultVO.getSuccess(), "", innerImportRosterDto.getFtbRosterInsertNomalVO().getPhone()));
        }

        asyncDeleteHistory(new ArrayList<>(userToHeadMap.keySet()), tenantCode, headers);
        return resultVOList;
    }

    private List<FtbPersonnelsRegistrationFormField> bachQueryField() {
        List<FtbPersonnelsRegistrationFormField> list = registrationFormFieldService.list(new QueryWrapper<FtbPersonnelsRegistrationFormField>()
                .lambda()
                .eq(FtbPersonnelsRegistrationFormField::getEnabledMark, 0) //1无效 0有效
                .eq(FtbPersonnelsRegistrationFormField::getStatus, 0) //0、启用  1、禁用
                .orderByAsc(FtbPersonnelsRegistrationFormField::getSorts));

        if (CollectionUtil.isNotEmpty(list)) {
            return list;
        }
        return new ArrayList<>();
    }

    private InnerImportResultVO updateImportOneRoster(FtbRosterInsertNomalVO ftbRosterInsertNomalVO, FtbPersonnelsStaffRoster entity, FtbPersonnelsStaffRoster oldRoster,
                                                      List<FtbPersonnelsRegistrationFormField> allFormFieldList, Map<String, FtbPersonnelsRegistrationFormField> allFormFieldListMap, List<FtbPersonnelsStaffRegistrationFormData> formDataValueList) {
        Map<String, FtbPersonnelsStaffRegistrationFormData> formFieldValueMap = personnelOrgUtils.convertFormValueMap(formDataValueList);
        Map<String, String> innerFieldValueCacheMap = ftbRosterInsertNomalVO.getInnerFieldValueCacheMap();
        //同步数据到formData
        Map<String, Object> formDataMap = convertToUpdateFormData(innerFieldValueCacheMap, allFormFieldList);
        formDataMap.put("probationPeriod", "");
        formDataMap.put("actualStartDate", "");
        formDataMap.put("companyAge", "");
        formDataMap.put("planProbationaryDate", "");
        formDataMap.put("actualProbationaryDate", "");

        LambdaUpdateWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaUpdateWrapper<>();
        String probationPeriod = innerFieldValueCacheMap.get("probationPeriod");

        ProbationPeriodDto probationPeriodDto = new ProbationPeriodDto(probationPeriod, "0");
        Date now = new Date();
        //写入数据库
        String planProbationaryDate = "";//计划转正日期
        if (entity.getActualStartDate() != null && StringUtils.isNotEmpty(probationPeriod)) {

            int month = personnelOrgUtils.calMonth(probationPeriodDto);
            Date toDay = DateUtil.offsetMonth(entity.getActualStartDate(), month);
            String toDayString = personnelOrgUtils.dateToString(toDay, "yyyy-MM-dd");
            planProbationaryDate = toDayString;
        }


        if (StringUtils.isEmpty(oldRoster.getWorkerNo()) && StringUtils.isNotEmpty(entity.getWorkerNo())) {
            wrapper.set(FtbPersonnelsStaffRoster::getWorkerNo, entity.getWorkerNo());
            formDataMap.put("workerNo", entity.getWorkerNo());
        }
        if (StringUtils.isEmpty(oldRoster.getCurrOrg()) && StringUtils.isNotEmpty(entity.getCurrOrg())) {
            wrapper.set(FtbPersonnelsStaffRoster::getCurrOrg, entity.getCurrOrg());
            formDataMap.put("currOrg", entity.getCurrOrg());
        }
        if (StringUtils.isEmpty(oldRoster.getCurrPosition()) && StringUtils.isNotEmpty(entity.getCurrPosition())) {
            wrapper.set(FtbPersonnelsStaffRoster::getCurrPosition, entity.getCurrPosition());
            formDataMap.put("currPosition", entity.getCurrPosition());
        }
        if (StringUtils.isEmpty(oldRoster.getCurrRank()) && StringUtils.isNotEmpty(entity.getCurrRank())) {
            wrapper.set(FtbPersonnelsStaffRoster::getCurrRank, entity.getCurrRank());
            formDataMap.put("currRank", entity.getCurrRank());
        }
        if (StringUtils.isEmpty(oldRoster.getCurrShopId()) && StringUtils.isNotEmpty(entity.getCurrShopId())) {
            wrapper.set(FtbPersonnelsStaffRoster::getCurrShopId, entity.getCurrShopId());
            formDataMap.put("currShopId", entity.getCurrShopId());
        }
        if (null == oldRoster.getEntrySalary() && null != entity.getEntrySalary()) {
            wrapper.set(FtbPersonnelsStaffRoster::getEntrySalary, entity.getEntrySalary());
            formDataMap.put("entrySalary", entity.getEntrySalary());
        }
        if (StringUtils.isEmpty(oldRoster.getCurrReportsTo()) && StringUtils.isNotEmpty(entity.getCurrReportsTo())) {
            wrapper.set(FtbPersonnelsStaffRoster::getCurrReportsTo, entity.getCurrReportsTo());
            formDataMap.put("currReportsTo", entity.getCurrReportsTo());
        }
        //老的试用期
        Boolean isProbationPeriod = false;
        FtbPersonnelsStaffRegistrationFormData oldProbationPeriod = formFieldValueMap.get("probationPeriod");
        if (oldProbationPeriod != null) {
            if (StringUtils.isNotEmpty(oldProbationPeriod.getValue()) && oldProbationPeriod.getValue().startsWith("{")) {
                ProbationPeriodDto bean = JSONUtil.toBean(oldProbationPeriod.getValue(), ProbationPeriodDto.class);
                String key = bean.getType();
                if (StringUtils.isNotEmpty(key)) {
                    isProbationPeriod = true;
                }
            }
        }
        //是否又技化转正
        Boolean isplanProbationaryDate = false;
        FtbPersonnelsStaffRegistrationFormData oldplanProbationaryDate = formFieldValueMap.get("planProbationaryDate");
        if (oldplanProbationaryDate != null) {
            if (StringUtils.isNotEmpty(oldplanProbationaryDate.getValue())) {
                isplanProbationaryDate = true;
            }
        }
        //实际转正
        FtbPersonnelsStaffRegistrationFormData oldActualProbationaryDate = formFieldValueMap.get("actualProbationaryDate");
        Boolean isactualProbationaryDate = false;
        if (oldActualProbationaryDate != null) {
            if (StringUtils.isNotEmpty(oldActualProbationaryDate.getValue())) {
                isactualProbationaryDate = true;
            }
        }
        if (oldRoster.getWorkerStatus().equals(StaffWorkerStatus.FULL_TIME.getCode()) || oldRoster.getWorkerStatus().equals(StaffWorkerStatus.PENDING_RESIGNATION.getCode())) {

            if (null == oldRoster.getActualStartDate() && isProbationPeriod == false && isplanProbationaryDate == false) {
                if (null != entity.getActualStartDate()) {
                    wrapper.set(FtbPersonnelsStaffRoster::getActualStartDate, entity.getActualStartDate());
                    formDataMap.put("actualStartDate", personnelOrgUtils.dateToString(entity.getActualStartDate(), "yyyy-MM-dd"));

                    if (now.after(entity.getActualStartDate())) {
                        long betweenDay = DateUtil.betweenDay(entity.getActualStartDate(), new Date(), false);
                        formDataMap.put("companyAge", String.valueOf(betweenDay));
                    } else {
                        formDataMap.put("companyAge", "0");
                    }
                }
                if (StringUtils.isNotEmpty(probationPeriod)) {
                    formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
                }
                if (StringUtils.isNotEmpty(planProbationaryDate)) {
                    formDataMap.put("planProbationaryDate", planProbationaryDate);
                }

            } else if (null != oldRoster.getActualStartDate() && isProbationPeriod == false && isplanProbationaryDate == false) {
                if (isProbationPeriod == false && StringUtils.isNotEmpty(probationPeriod)) {
                    formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
                    Date toDay = DateUtil.offsetMonth(oldRoster.getActualStartDate(), personnelOrgUtils.calMonth(probationPeriodDto));
                    String toDayString = personnelOrgUtils.dateToString(oldRoster.getActualStartDate(), "yyyy-MM-dd");
                    planProbationaryDate = toDayString;
                    formDataMap.put("planProbationaryDate", planProbationaryDate);
                }

            } else {
                if (null == oldRoster.getActualStartDate() && null != entity.getActualStartDate()) {
                    wrapper.set(FtbPersonnelsStaffRoster::getActualStartDate, entity.getActualStartDate());
                    formDataMap.put("actualStartDate", personnelOrgUtils.dateToString(entity.getActualStartDate(), "yyyy-MM-dd"));
                    if (now.after(entity.getActualStartDate())) {
                        long betweenDay = DateUtil.betweenDay(entity.getActualStartDate(), new Date(), false);
                        formDataMap.put("companyAge", String.valueOf(betweenDay));
                    } else {
                        formDataMap.put("companyAge", "0");
                    }
                }
                if (isProbationPeriod == false && StringUtils.isNotEmpty(probationPeriod)) {
                    formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
                }

                if (isplanProbationaryDate == false && StringUtils.isNotEmpty(planProbationaryDate)) {
                    formDataMap.put("planProbationaryDate", planProbationaryDate);
                }
            }

            String newactualProbationaryDate = innerFieldValueCacheMap.get("actualProbationaryDate");
            if (isactualProbationaryDate == false && StringUtils.isNotEmpty(newactualProbationaryDate)) {
                wrapper.set(FtbPersonnelsStaffRoster::getActualProbationaryDate, personnelOrgUtils.stringDateToDate(newactualProbationaryDate));
                formDataMap.put("actualProbationaryDate", newactualProbationaryDate);
            }


        } else {

            if (null != oldRoster.getActualStartDate() && isProbationPeriod == false && StringUtils.isNotEmpty(probationPeriod)) {
                if (isProbationPeriod == false && StringUtils.isNotEmpty(probationPeriod)) {
                    formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
                    Date toDay = DateUtil.offsetMonth(oldRoster.getActualStartDate(), personnelOrgUtils.calMonth(probationPeriodDto));
                    String toDayString = personnelOrgUtils.dateToString(oldRoster.getActualStartDate(), "yyyy-MM-dd");
                    planProbationaryDate = toDayString;
                    formDataMap.put("planProbationaryDate", planProbationaryDate);
                }
            } else {
                if (null == oldRoster.getActualStartDate() && null != entity.getActualStartDate()) {
                    wrapper.set(FtbPersonnelsStaffRoster::getActualStartDate, entity.getActualStartDate());
                    formDataMap.put("actualStartDate", personnelOrgUtils.dateToString(entity.getActualStartDate(), "yyyy-MM-dd"));
                    if (now.after(entity.getActualStartDate())) {
                        long betweenDay = DateUtil.betweenDay(entity.getActualStartDate(), new Date(), false);
                        formDataMap.put("companyAge", String.valueOf(betweenDay));
                    } else {
                        formDataMap.put("companyAge", "0");
                    }
                }

                if (isProbationPeriod == false && StringUtils.isNotEmpty(probationPeriod)) {
                    formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
                }

                if (isplanProbationaryDate == false && StringUtils.isNotEmpty(planProbationaryDate)) {
                    formDataMap.put("planProbationaryDate", planProbationaryDate);
                }
            }
            formDataMap.put("actualProbationaryDate", "");
            wrapper.set(FtbPersonnelsStaffRoster::getActualProbationaryDate, null);
        }


        if (StringUtils.isEmpty(oldRoster.getWorkerType()) && StringUtils.isNotEmpty(entity.getWorkerType())) {
            wrapper.set(FtbPersonnelsStaffRoster::getWorkerType, entity.getWorkerType());
            formDataMap.put("workerType", entity.getWorkerType());
        }

        wrapper.set(FtbPersonnelsStaffRoster::getUserId, oldRoster.getUserId());

        wrapper.eq(FtbPersonnelsStaffRoster::getId, oldRoster.getId());
        wrapper.set(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        this.update(wrapper);

        String workAddress = innerFieldValueCacheMap.get("workAddress");
        if (StringUtils.isNotEmpty(workAddress)) {
            WorkAddressDto workAddressDto = new WorkAddressDto();
            workAddressDto.setAddress(workAddress);
            formDataMap.put("workAddress", JSONUtil.toJsonStr(workAddressDto));
        }
        addRunBirthday(formDataMap);
        registrationFormDataService.importUpdateData(formDataMap, oldRoster.getPhone(), oldRoster.getId(), allFormFieldListMap, formFieldValueMap);

        batchUpdateAccount(entity, oldRoster, formDataMap, innerFieldValueCacheMap);
        InnerImportResultVO resultVO = new InnerImportResultVO();
        resultVO.setSuccess(true);
        return resultVO;
    }


    private Map<String, Object> convertToUpdateFormData(Map<String, String> valueMap, List<FtbPersonnelsRegistrationFormField> allFormFieldList) {
        Map<String, Object> map = new HashMap<>();
        if (CollectionUtil.isEmpty(allFormFieldList)) {
            return map;
        }
        for (FtbPersonnelsRegistrationFormField field : allFormFieldList) {
            String val = valueMap.get(field.getId());
            if (StringUtils.isNotEmpty(val)) {
                map.put(field.getId(), val);
            }
        }
        return map;
    }


    private Map<String, String> batchWritePlatAccount(List<InnerImportRosterDto> innerImportDtoList, Map<String, String> phoneUserMap, UserInfo userInfo) {

        String tenantId = personnelOrgUtils.getTenantId();
        Map<String, String> headers = personnelOrgUtils.getHeadersForLogin();

        Map<String, String> userIdToHeadMap = new HashMap<>();//用户ID ->头像
        List<GenerateHeadFileForm> headLogoList = new ArrayList<>();
        for (InnerImportRosterDto innerImportRosterDto : innerImportDtoList) {
            if (innerImportRosterDto.getFtbRosterInsertNomalVO().getIsNew()) {
                FtbPersonnelsStaffRoster newRoster = innerImportRosterDto.getNewRoster();
                String userId = phoneUserMap.get(newRoster.getPhone());
                GenerateHeadFileForm form = new GenerateHeadFileForm();
                form.setName(newRoster.getName());
                String filename = UUID.randomUUID() + ".png";
                form.setFilename(filename);
                headLogoList.add(form);
                userIdToHeadMap.put(userId, filename);
            }
        }
        if (CollectionUtil.isNotEmpty(headLogoList)) {
            personnelAsyncServiceUtils.batchGeneralHead(headLogoList, tenantId, headers);
        }
        List<UserAccountDto> platUserAccountDtoList = new ArrayList<>();
        for (InnerImportRosterDto innerImportRosterDto : innerImportDtoList) {
            if (!innerImportRosterDto.getFtbRosterInsertNomalVO().getIsNew()) {
                continue;
            } else {
                FtbPersonnelsStaffRoster newRoster = innerImportRosterDto.getNewRoster();
                FtbRosterInsertNomalVO ftbRosterInsertNomalVO = innerImportRosterDto.getFtbRosterInsertNomalVO();
                String userId = phoneUserMap.get(newRoster.getPhone());
                //生成主账号
                UserAccountDto userAccountDto = new UserAccountDto();
                userAccountDto.setFid(userId);
                userAccountDto.setUserName(newRoster.getName());
                userAccountDto.setTenantId(userInfo.getTenantId());
                userAccountDto.setUserMobilePhone(newRoster.getPhone());
                String userHeadLog = userIdToHeadMap.get(userId);
                userAccountDto.setHeadImageUrl(userHeadLog);
                String flowerName = ftbRosterInsertNomalVO.getInnerFieldValueCacheMap().get("flowerName");
                if (StringUtils.isNotEmpty(flowerName)) {
                    userAccountDto.setUserNickName(flowerName);
                }
                platUserAccountDtoList.add(userAccountDto);
            }
        }

        if (CollectionUtil.isNotEmpty(platUserAccountDtoList)) {
            List<List<UserAccountDto>> allList = groupByBatchTenant(platUserAccountDtoList, 50);
            ActionResult<List<UserAccountDto>> actionResult = null;
            for (List<UserAccountDto> userAccountDtos : allList) {
                try {
                    actionResult = pTenantAccountApi.batchAddUserAccount(userAccountDtos);
                    log.error("create main user={},result={}", JSONUtil.toJsonStr(userAccountDtos), JSONUtil.toJsonStr(actionResult));
                    if (null == actionResult || !actionResult.getCode().equals(200) || CollectionUtil.isEmpty(actionResult.getData())) {
                        throw new RuntimeException("账号生成失败了");
                    }
                } catch (Exception e) {
                    personnelOrgUtils.rollbackTenantUser(userAccountDtos);
                    throw new RuntimeException("账号生成失败了");
                }
                batchFillAccountForUserId(actionResult.getData(), tenantId, headers);
            }
        }
        return userIdToHeadMap;
    }

    private Map<String, String> batchWriteTenant(List<InnerImportRosterDto> innerImportDtoList) {
        Map<String, String> retMap = new HashMap<>();//手机号->到用户ID
        //查询用户
        List<String> phoneList = new ArrayList<>();
        for (InnerImportRosterDto vo : innerImportDtoList) {
            if (vo.getFtbRosterInsertNomalVO().getIsNew()) {
                phoneList.add(vo.getNewRoster().getPhone());
            }
        }
        //
        List<UserInfoVO> exiestUser = personnelOrgUtils.queryTenantAccountForPhoneList(phoneList);
        Map<String, UserInfoVO> exisetUserMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(exiestUser)) {
            for (UserInfoVO userInfoVO : exiestUser) {
                exisetUserMap.put(userInfoVO.getMobilePhone(), userInfoVO);
            }
        }


        //生成系统租户账号
        List<SaveUserManagerAddDTO> userManagerAddDTOList = new ArrayList<>();
        for (InnerImportRosterDto vo : innerImportDtoList) {
            if (!vo.getFtbRosterInsertNomalVO().getIsNew()) {
                retMap.put(vo.getOldRoster().getPhone(), vo.getOldRoster().getUserId());
                continue;
            }
            FtbPersonnelsStaffRoster entity = vo.getNewRoster();
            UserInfoVO userInfoVO = exisetUserMap.get(entity.getPhone());
            if (null != userInfoVO) {
                retMap.put(entity.getPhone(), userInfoVO.getId());
                continue;
            }
            Map<String, String> importInfoMap = vo.getFtbRosterInsertNomalVO().getInnerFieldValueCacheMap();
            String workerSex = importInfoMap.get("workerSex");
            String flowerName = importInfoMap.get("flowerName");
            if (null == workerSex) {
                workerSex = "0";
            }
            SaveUserManagerAddDTO userManagerAddDTO = new SaveUserManagerAddDTO();
            userManagerAddDTO.setAccount(ACCOUNT_TEMP_PRE + entity.getPhone());
            userManagerAddDTO.setMobilePhone(entity.getPhone());
            userManagerAddDTO.setRealName(entity.getName());
            userManagerAddDTO.setNickName(flowerName);
            if (StringUtils.isEmpty(workerSex)) {
                userManagerAddDTO.setGender(3);
            } else {
                userManagerAddDTO.setGender(Integer.valueOf(workerSex));
            }
            userManagerAddDTO.setJobStatus(personnelOrgUtils.convertAccountStatus(entity.getWorkerStatus()));
            userManagerAddDTO.setOrgId(entity.getCurrOrg());
            userManagerAddDTO.setPositionId(entity.getCurrPosition());
            userManagerAddDTO.setPositionGradesId(entity.getCurrRank());
            userManagerAddDTO.setManagerId(entity.getCurrReportsTo());
            if (null != entity.getActualStartDate()) {
                userManagerAddDTO.setEntryDate(entity.getActualStartDate());
            }
            userManagerAddDTOList.add(userManagerAddDTO);
        }

        List<UserBoundPhoneVO> retList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(userManagerAddDTOList)) {
            try {
                retList = userApi.userManagerBoundListAdd(userManagerAddDTOList);
                log.error("生成租户账号,dto={},rs={}", JSONUtil.toJsonStr(userManagerAddDTOList), JSONUtil.toJsonStr(retList));
                if (CollectionUtil.isEmpty(retList)) {
                    throw new RuntimeException("生成账户失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("生成账户失败");
            }
        }
        for (UserBoundPhoneVO userBoundPhoneVO : retList) {
            retMap.put(userBoundPhoneVO.getMobilePhone(), userBoundPhoneVO.getId());
        }
        // 更新用户主岗
        userManagerAddDTOList.forEach(item -> {
            // 更新用户主岗
            BaseUserPrimaryPositionDTO positionDTO = new BaseUserPrimaryPositionDTO();
            positionDTO.setUserId(retMap.get(item.getMobilePhone()));
            positionDTO.setOrganizeId(item.getOrgId());
            positionDTO.setPositionId(item.getPositionId());
            positionDTO.setPositionGradesId(item.getPositionGradesId());
            positionDTO.setManagerId(item.getManagerId());
            userPrimaryPositionApi.updateUserPrimaryPosition(positionDTO);
        });
        return retMap;

    }

    void batchUpdateAccount(FtbPersonnelsStaffRoster newRoster, FtbPersonnelsStaffRoster oldRoster, Map<String, Object> importInfoMap, Map<String, String> innerFieldValueCacheMap) {


        String workerSex = (String) importInfoMap.get("workerSex");
        String flowerName = (String) importInfoMap.get("flowerName");
        String workerName = (String) importInfoMap.get("workerName");
        String actualStartDate = (String) importInfoMap.get("actualStartDate");
        String birthday = (String) importInfoMap.get("birthday");
        String actualProbationaryDate = (String) importInfoMap.get("actualProbationaryDate");
        String idCardNum = (String) importInfoMap.get("idCardNum");

        SaveUserManagerAddDTO userManagerAddDTO = new SaveUserManagerAddDTO();
        Boolean isUpdate = false;
        userManagerAddDTO.setUserId(oldRoster.getUserId());
        if (StringUtils.isNotEmpty(workerName) && StringUtils.isEmpty(oldRoster.getName())) {
            isUpdate = true;
            userManagerAddDTO.setRealName(workerName);
        }
        if (StringUtils.isNotEmpty(workerSex)) {
            isUpdate = true;
            userManagerAddDTO.setGender(Integer.valueOf(workerSex));
        }
        if (StringUtils.isNotEmpty(flowerName)) {
            isUpdate = true;
            userManagerAddDTO.setNickName(flowerName);
        }

        if (StringUtils.isNotEmpty(actualProbationaryDate)) {
            isUpdate = true;
            userManagerAddDTO.setBecomeDate(DateUtil.parse(actualProbationaryDate, "yyyy-MM-dd"));
        }

        if (StringUtils.isNotEmpty(actualStartDate)) {
            isUpdate = true;
            userManagerAddDTO.setEntryDate(DateUtil.parse(actualStartDate, "yyyy-MM-dd"));
        }
        if (StringUtils.isNotEmpty(birthday)) {
            isUpdate = true;
            userManagerAddDTO.setBirthday(DateUtil.parse(birthday, "yyyy-MM-dd"));
        }

        if (StringUtils.isNotEmpty(actualStartDate)) {
            isUpdate = true;
            userManagerAddDTO.setEntryDate(newRoster.getActualStartDate());
        }

        if (StringUtils.isNotEmpty(idCardNum)) {
            isUpdate = true;
            userManagerAddDTO.setCertificatesNumber(idCardNum);
            userManagerAddDTO.setCertificatesType("a745d425adbb4321880817661cae8910");
        }

        if (isUpdate) {
            personnelOrgUtils.batchSysTenantAccountBase(List.of(userManagerAddDTO));
        }
    }

    private void syncImportFormData(FtbRosterInsertNomalVO ftbRosterInsertNomalVO, Map<String, Object> formDataMap) {

        List<FtbRosterInsertAttributesVO> voList = ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS();
        if (CollectionUtil.isNotEmpty(voList)) {
            for (FtbRosterInsertAttributesVO vo : voList) {
                formDataMap.put(vo.getFormFieldId(), vo.getAttributeValue());
            }
        }
    }

    private String getImportFormDataForFieldId(FtbRosterInsertNomalVO ftbRosterInsertNomalVO, String fieldId) {

        List<FtbRosterInsertAttributesVO> voList = ftbRosterInsertNomalVO.getFtbRosterInsertAttributesVOS();
        if (CollectionUtil.isNotEmpty(voList)) {
            for (FtbRosterInsertAttributesVO vo : voList) {
                if (fieldId.equals(vo.getFormFieldId())) {
                    return vo.getAttributeValue();
                }
            }
        }
        return "";
    }

    @Override
    public List<FtbRosterImportTemplateBO> queryRosterInfoByIds(List<String> ids, List<String> formFieldOptionIds,String schemeId) {
        //查询字段
        List<ExportFormTypeDto> allFields = rosterExportUtils.getExportFormTypes(formFieldOptionIds,schemeId);
        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        //查询选项
        QueryWrapper<FtbPersonnelsRegistrationFormFieldOption> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbPersonnelsRegistrationFormFieldOption::getEnabledMark, 0).orderByAsc(FtbPersonnelsRegistrationFormFieldOption::getId);
        List<FtbPersonnelsRegistrationFormFieldOption> optionList = fieldOptionService.list(wrapper);
        //查询花名册
        List<ExportRosterOneVo> rosterDataList = new ArrayList<>();
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectBatchIds(ids);


        List<FtbPersonnelsStaffRegistrationFormData> allFormDataList = registrationFormDataService.queryFormFieldValueForRosterIds(ids);
        //按照rosterid分组
        Map<String, List<FtbPersonnelsStaffRegistrationFormData>> map = allFormDataList.stream().collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getRosterId));

        for (FtbPersonnelsStaffRoster roster : rosterList) {
            List<FtbPersonnelsStaffRegistrationFormData> formValue = map.getOrDefault(roster.getId(), new ArrayList<>());
            rosterDataList.add(new ExportRosterOneVo(roster, formValue));
        }
        return rosterExportUtils.convertToFtbRosterImportTemplateBO(allFields, optionList, rosterDataList);

    }

    @Override
    public CanDeleteMsg checkBatchDelete(List<String> ids) {
        List<CheckRosterDeleteVo> list = new ArrayList<>();
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectBatchIds(ids);
        for (FtbPersonnelsStaffRoster roster : rosterList) {
            String checkFlag = ftbPersonnelsAuditRunTaskService.checkWhetherTheCurrentPersonnelIsInTheReviewProcess(roster.getUserId());
            LambdaQueryWrapper<FtbPersonnelsSecondmentManagement> queryWrapper4 = Wrappers.lambdaQuery();
            queryWrapper4.eq(FtbPersonnelsSecondmentManagement::getUserId, roster.getUserId());
            queryWrapper4.in(FtbPersonnelsSecondmentManagement::getTransferStatus, 1);
            queryWrapper4.eq(FtbPersonnelsSecondmentManagement::getEnableMark, 0);
            long count1 = secondmentManagementService.count(queryWrapper4);
            if (count1 > 0 && StringUtils.isEmpty(checkFlag)) {
                checkFlag = "借调";
            }
            if (StringUtils.isNotEmpty(checkFlag)) {
                list.add(convertToCheckRosterDeleteVo(roster, 3, false));
                continue;
            }
            ActionResult actionResult = flowTaskApi.checkReloadWait(roster.getUserId());
            if (actionResult != null && actionResult.getCode() == 200 && (boolean) actionResult.getData()) {
                list.add(convertToCheckRosterDeleteVo(roster, 3, true));
            }
        }
        if (CollectionUtil.isNotEmpty(list)) {
            return new CanDeleteMsg(false, "不能删除", list);
        } else {
            return new CanDeleteMsg(true, "可以删除");
        }
    }

    /**
     * 试岗驳回接口
     *
     * @param userId
     * @param dto
     */
    @Override
    @Transactional
    public void innerTravelFail(String userId, StaffTravlFailDto dto) {
        FtbPersonnelsStaffRoster roster = queryRosterInfoByUserId(userId);

        if (null != roster) {
            FtbPersonnelsStaffRoster updateRoster = new FtbPersonnelsStaffRoster();
            updateRoster.setUserId(userId);
            updateRoster.setWorkerStatus(dto.getStaffWorkerStatus().getCode());
            updateRoster.setId(roster.getId());
            updateRoster.setDepartDate(new Date());
            if (StringUtils.isNotEmpty(dto.getRemarks())) {
                updateRoster.setTrialFail(dto.getRemarks());
            }
            if (dto.getStaffWorkerStatus().getCode().equals(StaffWorkerStatus.PENDING_RESIGNATION.getCode())) {
                updateRoster.setIsTrialFail(1);
            }

            baseMapper.updateById(updateRoster);

            registrationFormDataService.updateForOneField(roster.getId(), roster.getPhone(), "workerStatus", dto.getStaffWorkerStatus().getCode());

            if (dto.getStaffWorkerStatus().getCode().equals(StaffWorkerStatus.RESIGNED.getCode())) {
                QueryWrapper<FtbPersonnelsStaffEmploymentApply> removeWrapper = new QueryWrapper<>();
                removeWrapper.lambda().eq(FtbPersonnelsStaffEmploymentApply::getPhone, roster.getPhone());
                //同步状态到内推池子
                personnelOrgUtils.sysWorkerStatusToUchisuike(roster.getPhone(), StaffWorkerStatus.RESIGNED.getCode());
                staffEmploymentApplyService.remove(removeWrapper);


                //同步离职日期
                SaveUserManagerAddDTO saveUserManagerAddDTO = new SaveUserManagerAddDTO();
                saveUserManagerAddDTO.setUserId(roster.getUserId());
                saveUserManagerAddDTO.setDepartDate(new Date());
                personnelOrgUtils.sysTenantAccountBase(saveUserManagerAddDTO);

                String s = personnelOrgUtils.dateToString(roster.getCreatorTime(), "yyyy-MM-dd");
                //员工成长
                dto.setDutyDate(personnelOrgUtils.stringDateToDate(s));
                AddGrowthLogDto addGrowthLogDto = new AddGrowthLogDto();
                addGrowthLogDto.setUserId(userId);
                addGrowthLogDto.setChangeDate(new Date());
                addGrowthLogDto.setGrowthType(GrowthLogEnum.PRE_TRAIL.getCode());
                StaffDepartDto staffDepartDto = StaffDepartDto.covert(dto);
                addGrowthLogDto.setDetail(JSONUtil.toJsonStr(staffDepartDto));

                // 试岗
                growthLogService.addGrowthLog(addGrowthLogDto);

                List<FormTypeDto> list = registrationFormDataService.queryArchivalForm(userId);
                list = removeOptionData(list);
                FtbPersonnelsStaffArchivesHistory history = new FtbPersonnelsStaffArchivesHistory();
                history.setUserId(userId);
                history.setArchives(JSONUtil.toJsonStr(list));
                history.setEnabledMark(1);
                history.setCreatorTime(new Date());
                ftbPersonnelsStaffArchivesHistoryService.save(history);

                //离职清除老数据
                QueryWrapper<FtbPersonnelsStaffRegistrationFormData> formDataUpdateWrapper = new QueryWrapper<>();
                formDataUpdateWrapper.lambda().eq(FtbPersonnelsStaffRegistrationFormData::getRosterId, roster.getId());
                registrationFormDataService.remove(formDataUpdateWrapper);
            }
        }

    }

    /**
     * 修改员工司年龄
     */
    @Override
    public void updateCompanyAge() {
        Date now = new Date();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getPhone, FtbPersonnelsStaffRoster::getActualStartDate)
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus, "305")
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            for (FtbPersonnelsStaffRoster roster : rosterList) {
                if (null != roster.getActualStartDate() && StringUtils.isNotEmpty(roster.getPhone())) {
                    long betweenDay = 0L;
                    if (now.after(roster.getActualStartDate())) {
                        betweenDay = DateUtil.betweenDay(roster.getActualStartDate(), new Date(), false);
                    }
                    registrationFormDataService.updateForOneField(roster.getId(), roster.getPhone(), "companyAge", String.valueOf(betweenDay));
                }
            }
        }
    }

    @Override
    public void updateWorkerAge() {
        Date now = new Date();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getPhone, FtbPersonnelsStaffRoster::getActualStartDate)
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus, "305")
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            for (FtbPersonnelsStaffRoster roster : rosterList) {
                FtbPersonnelsStaffRegistrationFormData formData = registrationFormDataService.queryOneFieldForFieldId(roster.getId(), "birthday");
                if (formData != null && StringUtils.isNotEmpty(formData.getValue())) {
                    String birthday = formData.getValue();
                    Date birth = personnelOrgUtils.stringDateToDate(birthday);
                    int age = personnelOrgUtils.calculateAge(personnelOrgUtils.dateToLocalDate(birth));
                    String currAge = age + "岁";
                    registrationFormDataService.updateForOneField(roster.getId(), roster.getPhone(), "age", currAge);
                }
            }
        }
    }

    @Override
    public List<FtbPersonnelsStaffRosterDto> queryWithUserIds(StaffRosterListReq req) {
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = Wrappers.lambdaQuery();
        //wrapper.select(FtbPersonnelsStaffRoster::getUserId);
        wrapper.in(CollectionUtil.isNotEmpty(req.getUserIds()), FtbPersonnelsStaffRoster::getUserId, req.getUserIds());
        wrapper.eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        wrapper.eq(StringUtils.isNotEmpty(req.getWorkerStatus()), FtbPersonnelsStaffRoster::getWorkerStatus, req.getWorkerStatus());
        List<FtbPersonnelsStaffRoster> list = baseMapper.selectList(wrapper);
        return list.stream().map(FtbPersonnelsStaffRosterDto::changeEscape).collect(Collectors.toList());
    }


    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Boolean bindPhone(String userId, String phone) {
        log.error("正常日志，bindPhone,userId={},phone={}", userId, phone);
        //当前人员还未入花名册
        FtbPersonnelsStaffRoster roster = queryRosterInfoByUserId(userId);
        FtbPersonnelsStaffRoster rosterPhone = queryRosterInfoByPhone(phone);
        if (null != rosterPhone) {
            if (!rosterPhone.getUserId().equals(userId)) {
                log.error("错误日志，bindPhone,userId={},phone={},花名册中手机号已存在,不能绑定", userId, phone);
               throw new RuntimeException("花名册中手机号已存在,不能绑定");
            }
        }
        if (null == roster) {
           // 查询当前用户是否存在入职管理
            LambdaQueryWrapper<FtbPersonnelsStaffEmploymentApply> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getUserId, userId);
            queryWrapper.or();
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getPhone, phone);
            FtbPersonnelsStaffEmploymentApply one = staffEmploymentApplyService.getOne(queryWrapper);
            if (Objects.nonNull(one)) {
                // 更改入职管理手机号
                LambdaUpdateWrapper<FtbPersonnelsStaffEmploymentApply> wrapperApply = Wrappers.lambdaUpdate();
                wrapperApply.set(FtbPersonnelsStaffEmploymentApply::getPhone, phone);
                wrapperApply.eq(FtbPersonnelsStaffEmploymentApply::getId, one.getId());
                staffEmploymentApplyService.update(new FtbPersonnelsStaffEmploymentApply(),wrapperApply);
                // 获取旧手机号
                String onePhone = one.getPhone();
                //查询手机号字段F
                LambdaQueryWrapper<FtbPersonnelsStaffRegistrationFormData> formDataLambdaQueryWrapper = Wrappers.lambdaQuery();
                formDataLambdaQueryWrapper.eq(FtbPersonnelsStaffRegistrationFormData::getPhone, onePhone);
                List<FtbPersonnelsStaffRegistrationFormData> formData = registrationFormDataService.list(formDataLambdaQueryWrapper);
                // 修改手机号
                List<FtbPersonnelsStaffRegistrationFormData> registrationFormData = formData.stream().map(v -> {
                    v.setPhone(phone);
                    if (v.getFormFieldId().equals("phone")) {
                        v.setValue(phone);
                    }
                    return v;
                }).collect(Collectors.toList());
                registrationFormDataService.updateBatchById(registrationFormData);
            }
        }else {
            // 查询当前用户是否存在入职管理
            LambdaQueryWrapper<FtbPersonnelsStaffEmploymentApply> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getUserId, userId);
            queryWrapper.or();
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getPhone, phone);
            FtbPersonnelsStaffEmploymentApply one = staffEmploymentApplyService.getOne(queryWrapper);
            if (Objects.nonNull(one)) {
                // 更改入职管理手机号
                LambdaUpdateWrapper<FtbPersonnelsStaffEmploymentApply> wrapperApply = Wrappers.lambdaUpdate();
                wrapperApply.set(FtbPersonnelsStaffEmploymentApply::getPhone, phone);
                wrapperApply.eq(FtbPersonnelsStaffEmploymentApply::getId, one.getId());
                staffEmploymentApplyService.update(new FtbPersonnelsStaffEmploymentApply(),wrapperApply);
            }
            //修改手机号
            LambdaUpdateWrapper<FtbPersonnelsStaffRoster> rosterLambdaUpdateWrapper = Wrappers.lambdaUpdate();
            rosterLambdaUpdateWrapper.set(FtbPersonnelsStaffRoster::getPhone, phone);
            rosterLambdaUpdateWrapper.eq(FtbPersonnelsStaffRoster::getId, roster.getId());
            baseMapper.update(new FtbPersonnelsStaffRoster(), rosterLambdaUpdateWrapper);
            //修改档案
            LambdaUpdateWrapper<FtbPersonnelsStaffRegistrationFormData> lambdaUpdate = Wrappers.lambdaUpdate();
            lambdaUpdate.eq(FtbPersonnelsStaffRegistrationFormData::getRosterId, roster.getId());
            lambdaUpdate.set(FtbPersonnelsStaffRegistrationFormData::getPhone, phone);
            registrationFormDataService.update(new FtbPersonnelsStaffRegistrationFormData(), lambdaUpdate);

            //查询手机号字段
            FtbPersonnelsStaffRegistrationFormData ftbPersonnelsStaffRegistrationFormData = registrationFormDataService.queryOneField(phone, roster.getId(), "phone");

            FtbPersonnelsStaffRegistrationFormData addSave;
            if (ftbPersonnelsStaffRegistrationFormData != null) {
                addSave = ftbPersonnelsStaffRegistrationFormData;
                addSave.setValue(phone);
            } else {
                addSave = new FtbPersonnelsStaffRegistrationFormData();
                addSave.setRosterId(roster.getId());
                addSave.setPhone(phone);
                addSave.setFormTypeId("1");
                addSave.setFormFieldId("phone");
                addSave.setValue(phone);
            }
            // 转正手机号修改
            LambdaUpdateWrapper<FtbPersonnelsRegularManagement> reg = Wrappers.lambdaUpdate();
            reg.eq(FtbPersonnelsRegularManagement::getUserId, userId);
            reg.set(FtbPersonnelsRegularManagement::getPhoneNumber,phone);
            regularManagementService.update(new FtbPersonnelsRegularManagement(),reg);
            // 离职手机号修改
            LambdaUpdateWrapper<FtbPersonnelsTurnoverManagement> wrapper = Wrappers.lambdaUpdate();
            wrapper.set(FtbPersonnelsTurnoverManagement::getPhoneNumber, phone);
            wrapper.eq(FtbPersonnelsTurnoverManagement::getUserId, userId);
            turnoverManagementMapper.update(new FtbPersonnelsTurnoverManagement(),wrapper);
            registrationFormDataService.saveOrUpdate(addSave);
        }
        return true;
    }

    /**
     * 查询员工id
     *
     * @param userIds
     * @return
     */

    @Override
    public List<FtbPersonnelsStaffRoster> queryWorkerIdByUserIds(List<String> userIds) {
        if (CollectionUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getSystemWokerId, FtbPersonnelsStaffRoster::getUserId
                        , FtbPersonnelsStaffRoster::getName)
                .in(FtbPersonnelsStaffRoster::getUserId, userIds);
        return baseMapper.selectList(wrapper);

    }

    /**
     * 查询员工id
     *
     * @param userIds
     * @return
     */

    @Override
    public List<FtbPersonnelsStaffRoster> queryUerIdByWorkIds(List<String> userIds) {
        if (CollectionUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getSystemWokerId,
                        FtbPersonnelsStaffRoster::getUserId
                        , FtbPersonnelsStaffRoster::getName)
                .in(FtbPersonnelsStaffRoster::getUserId, userIds);
        return baseMapper.selectList(wrapper);

    }

    /**
     * 根据工人ID列表查询用户信息
     *
     * 此方法旨在通过一个或多个工人ID来检索相应的用户信息它首先检查输入的工人ID列表是否为空，
     * 如果为空，则返回一个空列表这样做是为了避免进行不必要的数据库查询当ID列表不为空时，
     * 方法会构造一个查询条件，选择特定的字段，并根据系统工人ID进行查询
     *
     * @param workerIds 工人ID列表，用于查询用户信息如果列表为空或null，将返回一个空列表
     * @return 返回一个包含查询到的用户信息的列表如果无任何匹配的记录，将返回一个空列表
     */
    @Override
    public List<FtbPersonnelsStaffRoster> queryUserInfoByWorkerId(List<String> workerIds) {
        // 检查输入的工人ID列表是否为空或null，如果为空，直接返回一个空列表
        if (CollectionUtil.isEmpty(workerIds)) {
            return new ArrayList<>();
        }
        // 构造查询条件，选择特定字段，并指定系统工人ID必须在给定的工人ID列表中
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getSystemWokerId, FtbPersonnelsStaffRoster::getUserId
                        , FtbPersonnelsStaffRoster::getName)
                .in(FtbPersonnelsStaffRoster::getSystemWokerId, workerIds);
        // 执行查询并返回结果列表
        return baseMapper.selectList(wrapper);
    }



    /**
     * 根据用户ID查询司龄
     *
     * @param userIds 用户id
     * @return
     */
    @Override
    public List<QueryCompanyAgeDto> queryCompanyAge(List<String> userIds) {
        List<QueryCompanyAgeDto> retList = new ArrayList<>();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getPhone, FtbPersonnelsStaffRoster::getActualStartDate)
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            for (FtbPersonnelsStaffRoster roster : rosterList) {
                QueryCompanyAgeDto dto = new QueryCompanyAgeDto();
                dto.setUserId(roster.getUserId());
                //查询司龄
                String companyAge = registrationFormDataService.queryOneFieldValue(roster.getPhone(), roster.getId(), "companyAge");
                if (StringUtils.isNotEmpty(companyAge)) {
                    dto.setConpanyAge(Long.valueOf(companyAge));
                } else {
                    dto.setConpanyAge(0L);
                }
                //查询工龄
                String workAge = registrationFormDataService.queryOneFieldValue(roster.getPhone(), roster.getId(), "workAge");
                if (StringUtils.isNotEmpty(workAge)) {
                    dto.setWorkerAge(Long.valueOf(workAge));
                } else {
                    dto.setWorkerAge(0L);
                }
                //入职日期
                String actualStartDate = registrationFormDataService.queryOneFieldValue(roster.getPhone(), roster.getId(), "actualStartDate");
                if (StringUtils.isNotEmpty(actualStartDate)) {
                    dto.setActualStartDate(actualStartDate);
                }
                //生日
                String birthday = registrationFormDataService.queryOneFieldValue(roster.getPhone(), roster.getId(), "birthday");
                if (StringUtils.isNotEmpty(birthday)) {
                    dto.setBirthday(birthday);
                }
                //员工名称
                String workerName = registrationFormDataService.queryOneFieldValue(roster.getPhone(), roster.getId(), "workerName");
                if (StrUtil.isNotBlank(workerName)) {
                    dto.setWorkerName(workerName);
                }
                retList.add(dto);
            }
        }
        return retList;
    }

    @Override
    public List<UserPageListVO> queryAllUserForOrgAndStatus(QueryUserListDTO dto) {
        String organizeId = dto.getOrganizeId();
        ActionResult<List<UserPageListVO>> actionResult = v2UserApi.listTargetOrganizes(List.of(organizeId), null,null);
        if (actionResult == null || CollUtil.isEmpty(actionResult.getData())) {
            return new ArrayList<>();
        }
        List<UserPageListVO> userListVOS = actionResult.getData();
        //获取所有用户ID
        List<String> userIds = userListVOS.stream().map(UserPageListVO::getId).collect(Collectors.toList());

        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(rosterList)) {
            return new ArrayList<>();
        }
        //转换成userid 的map
        Map<String, FtbPersonnelsStaffRoster> rosterMap = rosterList.stream().collect(Collectors.toMap(FtbPersonnelsStaffRoster::getUserId, Function.identity()));

        List<UserPageListVO> newList = new ArrayList<>();
        for (UserPageListVO vo : userListVOS) {
            FtbPersonnelsStaffRoster roster = rosterMap.get(vo.getId());
            if (null == roster) {
                continue;
            }
            if (roster.getEnabledMark() == 1) {
                continue;
            }
            if ("304".equals(roster.getWorkerStatus()) || "305".equals(roster.getWorkerStatus())) {
                continue;
            }
            newList.add(vo);
        }

        return newList;
    }

    /**
     * 检测是否档案管理员
     *
     * @param loginUserId
     * @return
     */
    @Override
    public Boolean checkMyIsArchiveManager(String loginUserId) {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(loginUserId);
        List<String> authList = personnelsPermissionsService.queryPermissionList(userInfo, "Employeer:list", 0);
        if (CollectionUtil.isEmpty(authList)) {
            return false;
        }
        if (authList.contains("Employeer:update")) {
            return true;
        }
        return false;
    }


    /**
     * 检测是否档案管理员
     *
     * @return
     */
    @Override
    public Boolean checkCurrLoginUserArchiveManager() {
        UserInfo user = UserProvider.getUser();
        List<String> authList = personnelsPermissionsService.queryPermissionList(user, "Employeer:list", 0);
        if (CollectionUtil.isEmpty(authList)) {
            return false;
        }
        if (authList.contains("Employeer:update")) {
            return true;
        }
        return false;
    }

    @Override
    public Integer checksItInTheReviewProcess(String id) {
        FtbPersonnelsStaffRoster roster = queryRosterAndCheckById(id);
        String checkFlag = ftbPersonnelsAuditRunTaskService.checkWhetherTheCurrentPersonnelIsInTheReviewProcess(roster.getUserId());
        if (StringUtils.isNotEmpty(checkFlag)) {
            return Integer.valueOf(checkFlag);
        }
        return 0;
    }


    private CheckRosterDeleteVo convertToCheckRosterDeleteVo(FtbPersonnelsStaffRoster roster, Integer noDeleteType, Boolean canDelete) {
        CheckRosterDeleteVo checkRosterDeleteVo = new CheckRosterDeleteVo();
        checkRosterDeleteVo.setUserId(roster.getUserId());
        checkRosterDeleteVo.setPhone(roster.getPhone());
        checkRosterDeleteVo.setName(roster.getName());
        checkRosterDeleteVo.setWorkerStatus(roster.getWorkerStatus());
        checkRosterDeleteVo.setNoDeleteType(noDeleteType);
        checkRosterDeleteVo.setRosterId(roster.getId());
        checkRosterDeleteVo.setCanDelete(canDelete);
        List<WorkerGroupDataDto> list = personnelOrgUtils.getUserOrgBoundInfo(roster.getUserId());
        checkRosterDeleteVo.setOrgList(list);
        return checkRosterDeleteVo;
    }

    private InnerImportResultVO addImportOneRoster(FtbRosterInsertNomalVO ftbRosterInsertNomalVO, FtbPersonnelsStaffRoster entity, FtbPersonnelsStaffRoster oldRoster,
                                                   UserInfo userInfo, Map<String, String> phoneUserMap, Map<String, String> userToHeadMap, Map<String, FtbPersonnelsRegistrationFormField> allFormFieldListMap) {
        Map<String, String> innerFieldValueCacheMap = ftbRosterInsertNomalVO.getInnerFieldValueCacheMap();
        String probationPeriod = innerFieldValueCacheMap.get("probationPeriod");
        if (StringUtils.isEmpty(probationPeriod)) {
            probationPeriod = "100";
        }
        ProbationPeriodDto probationPeriodDto = new ProbationPeriodDto(probationPeriod, "0");
        Date now = new Date();
        InnerImportResultVO resultVO = new InnerImportResultVO();
        String userId = phoneUserMap.get(entity.getPhone());
        if (StringUtils.isEmpty(userId)) {
            throw new RuntimeException("姓名：" + entity.getName() + ",手机号：" + entity.getPhone() + ",租户账户生成失败");
        }
        entity.setUserId(userId);
        //查询花名册中是否已经有数据
        if (null != oldRoster) {
            //重复入职
            entity.setId(oldRoster.getId());
            if (null != oldRoster.getJoinNum()) {
                entity.setJoinNum(oldRoster.getJoinNum() + 1);
            } else {
                entity.setJoinNum(1);
            }
        } else {
            //第一次入职
            entity.setJoinNum(1);
        }
        //生成员工ID
        entity.setSystemWokerId(generateSystemWorkerId());

        //写入数据库
        entity.setEnabledMark(0);
        entity.setIsSubmitForm(1);
        entity.setContractStatus(FContractSignStatus.NOT_INITIATED.getCode());
        entity.setIsTrialJob(0);
        entity.setTrialJobDay(0);
        String planProbationaryDate = "";//计划转正日期
        String actualProbationaryDate = "";//实际转正日期
        if (StaffWorkerStatus.TRIAL.getCode().equals(entity.getWorkerStatus())) {
            int month = personnelOrgUtils.calMonth(probationPeriodDto);
            Date toDay = DateUtil.offsetMonth(entity.getActualStartDate(), month);
            String toDayString = personnelOrgUtils.dateToString(toDay, "yyyy-MM-dd");
            planProbationaryDate = toDayString;
            actualProbationaryDate = "";

        } else if (StaffWorkerStatus.FULL_TIME.getCode().equals(entity.getWorkerStatus())) {
            entity.setActualProbationaryDate(entity.getActualStartDate());
            String toDayString = personnelOrgUtils.dateToString(entity.getActualStartDate(), "yyyy-MM-dd");
            planProbationaryDate = toDayString;
            actualProbationaryDate = toDayString;
        }
        entity.setIsTrialFail(0);

        entity.setTrialFail("");
        entity.setIsSignSeparation(0);
        entity.setCurrSalary(new BigDecimal(0));

        if (StringUtils.isEmpty(entity.getId())) {
            baseMapper.insert(entity);
        } else {
            baseMapper.updateById(entity);
        }
        registrationFormDataService.addRosterIdToFormData(entity.getPhone(), entity.getId());

        //同步数据到formData
        Map<String, Object> formDataMap = BeanUtil.beanToMap(entity);
        //同步到字段动态表
        syncImportFormData(ftbRosterInsertNomalVO, formDataMap);
        String headLogo = userToHeadMap.get(userId);
        List<String> headList = new ArrayList<>();
        headList.add(headLogo);
        formDataMap.put("headLogo", JSONUtil.toJsonStr(headList));
        formDataMap.put("actualStartDate", innerFieldValueCacheMap.get("actualStartDate"));
        formDataMap.put("planProbationaryDate", planProbationaryDate);

        if (StaffWorkerStatus.TRIAL.getCode().equals(entity.getWorkerStatus())) {
            formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
        } else if (StaffWorkerStatus.FULL_TIME.getCode().equals(entity.getWorkerStatus())) {
            probationPeriodDto = new ProbationPeriodDto("100", "0");
            formDataMap.put("probationPeriod", JSONUtil.toJsonStr(probationPeriodDto));
        }
        String workAddress = innerFieldValueCacheMap.get("workAddress");
        WorkAddressDto workAddressDto = new WorkAddressDto();
        workAddressDto.setAddress(workAddress);
        formDataMap.put("workAddress", JSONUtil.toJsonStr(workAddressDto));
        formDataMap.put("actualProbationaryDate", actualProbationaryDate);

        if (null != entity.getActualStartDate()) {
            if (now.after(entity.getActualStartDate())) {
                long betweenDay = DateUtil.betweenDay(entity.getActualStartDate(), new Date(), false);
                formDataMap.put("companyAge", String.valueOf(betweenDay));
            } else {
                formDataMap.put("companyAge", "0");
            }

        }
        addRunBirthday(formDataMap);
        asyncUpdateFormData(formDataMap, entity.getPhone(), entity.getId(), allFormFieldListMap);
        asyncDealImportRosterOtherData(entity, userInfo, probationPeriodDto);
        resultVO.setSuccess(true);
        return resultVO;
    }

    private void addRunBirthday(Map<String, Object> formDataMap) {
        // 身份证号码识别出生日期
        if (Objects.nonNull(formDataMap.get("idCardNum"))) {
            Date birthday = IdcardUtil.getBirthDate(formDataMap.get("idCardNum").toString()).toJdkDate();
            formDataMap.put("birthday", DateUtil.format(birthday, "yyyy-MM-dd"));
        }
        String birthday = (String) formDataMap.get("birthday");
        if (StringUtils.isNotEmpty(birthday)) {
            Date birth = personnelOrgUtils.stringDateToDate(birthday);
            int age = personnelOrgUtils.calculateAge(personnelOrgUtils.dateToLocalDate(birth));
            String currAge = age + "岁";
            formDataMap.put("age", currAge);
        }
    }


    private void asyncUpdateFormData(Map<String, Object> formDataMap, String phone, String rosterId, Map<String, FtbPersonnelsRegistrationFormField> allFormFieldListMap) {
        String tenantId = personnelOrgUtils.getTenantId();
        Map<String, String> header = personnelOrgUtils.getHeadersForLogin();
        personnelAsyncImportUtils.asyncUpdateFormData(formDataMap, phone, rosterId, allFormFieldListMap, tenantId, header);
    }

    private void asyncDealImportRosterOtherData(FtbPersonnelsStaffRoster entity, UserInfo userInfo, ProbationPeriodDto probationPeriodDto) {
        String tenantId = userInfo.getTenantId();
        String token = userInfo.getToken();
        if (StringUtils.isEmpty(token)) {
            token = "";
        }
        Map<String, String> headers = ImmutableMap.of(Constants.AUTHORIZATION.toLowerCase(), token);
        personnelAsyncImportUtils.asyncDealImportRosterOtherData(entity, probationPeriodDto, tenantId, headers);
    }

    private String getUserHeadLog(Map<String, FtbPersonnelsStaffRegistrationFormData> formMap, FtbPersonnelsStaffRoster entity) {
        String headLogo = personnelOrgUtils.getFormDataForField(formMap, "headLogo");
        if (StringUtils.isEmpty(headLogo) || "[]".equals(headLogo)) {
            headLogo = generaDefaultUserHeadLog(entity);
        } else {
            List<String> headList = JSONUtil.toList(headLogo, String.class);
            if (CollectionUtil.isNotEmpty(headList)) {
                headLogo = headList.get(0);
            } else {
                headLogo = "";
            }
            if (StringUtils.isEmpty(headLogo)) {
                headLogo = generaDefaultUserHeadLog(entity);
            }
        }
        if (StringUtils.isEmpty(headLogo)) {
            headLogo = DEFAULT_USER_LOGO;
        }
        return headLogo;
    }

    private String generaDefaultUserHeadLog(FtbPersonnelsStaffRoster entity) {
        String headLogo = DEFAULT_USER_LOGO;
        try {
            ActionResult headResult = pTenantAccountApi.generateDefaultAvatar(entity.getName());
            log.error("生成默认头像,name={},result={}", entity.getName(), JSONUtil.toJsonStr(headResult));
            if (null != headResult) {
                headLogo = (String) headResult.getData();
                registrationFormDataService.updateForOneField(entity.getPhone(), "headLogo", headLogo);
            }
        } catch (IOException e) {
            log.error("生成默认头像失败", e);
        }
        return headLogo;
    }

    public List<List<UserAccountDto>> splitIntoBatches(List<UserAccountDto> userAccountDtoList, Integer batchSize) {
        List<List<UserAccountDto>> batches = new ArrayList<>();
        for (int i = 0; i < userAccountDtoList.size(); i += batchSize) {
            int end = Math.min(i + batchSize, userAccountDtoList.size());
            batches.add(new ArrayList<>(userAccountDtoList.subList(i, end)));
        }
        return batches;
    }


    private String buildGrowthLogDetail(String currOrg, String currPosition, String currRank, String currReportsTo, Date actualStartDate) {
        StaffBaseInfoDto dto = new StaffBaseInfoDto();
        dto.setCurrOrg(currOrg);
        dto.setCurrPosition(currPosition);
        dto.setCurrRank(currRank);
        dto.setReportsTo(currReportsTo);
        personnelOrgUtils.fillOrgNameById(dto);
        personnelOrgUtils.fillPositionNameById(dto);
        personnelOrgUtils.fillRankNameById(dto);
        UserEntity userEntity = personnelOrgUtils.queryUserInfo(currReportsTo);
        if (null != userEntity) {
            dto.setReportsToName(userEntity.getRealName());
        }
        dto.setActualStartDate(actualStartDate);
        return JSONUtil.toJsonStr(dto);
    }


    /**
     * 根据手机号查询花名册信息
     *
     * @param phone
     * @return
     */

    public FtbPersonnelsStaffRoster queryRosterInfoByPhone(String phone) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getPhone, phone);
//        wrapper.lambda().last("limit 1");
//        wrapper.lambda().ne(FtbPersonnelsStaffRoster::getWorkerStatus,"305");
//        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getEnabledMark,0);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        return entity;
    }

    /**
     * 更加手机号批量查询花名册
     *
     * @param phones 手机号集合
     * @return
     */
    public List<FtbPersonnelsStaffRoster> queryRosterInfoByPhones(List<String> phones) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
//        wrapper.lambda().in(FtbPersonnelsStaffRoster::getPhone, phones).eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        wrapper.lambda().in(FtbPersonnelsStaffRoster::getPhone, phones);
        return baseMapper.selectList(wrapper);

    }

    /**
     * 根据用户ID查询花名册信息
     *
     * @param userId 用户ID
     * @return
     */

    public FtbPersonnelsStaffRoster queryRosterInfoByUserId(String userId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getUserId, userId);
        FtbPersonnelsStaffRoster entity = baseMapper.selectOne(wrapper);
        return entity;
    }

    /**
     * 根据员工工号查询花名册信息
     *
     * @param workderId 员工工号
     * @return
     */
    public List<FtbPersonnelsStaffRoster> queryRosterInfoByWorkerId(String workderId) {
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getWorkerNo, workderId);
        return baseMapper.selectList(wrapper);

    }

    /**
     * 根据员工系统id查询员工
     * @param systemId 系统id
     * @return 员工花名册列表
     */
    @Override
    public List<FtbPersonnelsStaffRoster> queryRosterInfoBySystemId(String systemId) {
        if (StringUtils.isEmpty(systemId)) {
            return new ArrayList<>();
        }
        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(FtbPersonnelsStaffRoster::getSystemWokerId, systemId);
        return baseMapper.selectList(wrapper);
    }



    @Override
    public FtbCultivatePromotionWithPersonelVO queryTrainData(String userId, String postId) {
        return promotionService.queryTrainData(userId, postId);
    }

    /**
     * 统计员工数量
     * 在职员工：工作状态为“试用+正式+待离职”
     * 全职员工：员工类型为“全职”
     * 兼职员工：员工类型为“兼职”
     * 实习员工：合同类型为“实习协议”
     * 待离职员工：工作状态为“待离职”
     * 正式员工：工作状态为“正式”
     * 试用员工：工作状态为“试用”
     *
     * @return
     */
    @Override
    public WorkerStatisticsDto statisticsWorkerNumber() {
        List<String> userIds = queryCacheAuthUserList(null, null);

        WorkerStatisticsDto dto = new WorkerStatisticsDto();
        if (userIds != null && userIds.isEmpty()) {
            return dto;
        }
        //在职
        Long jobNum = baseMapper.selectCount((new QueryWrapper<FtbPersonnelsStaffRoster>()).lambda()
                .in(FtbPersonnelsStaffRoster::getWorkerStatus, "302", "303", "304", "306")
                .in(CollUtil.isNotEmpty(userIds), FtbPersonnelsStaffRoster::getUserId, userIds)
                .ne(FtbPersonnelsStaffRoster::getUserId,"349057407209541")
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
        );
        dto.setJobNum(jobNum);

        /**
         * 实习员工数量
         */
        Long practiceNum = baseMapper.selectCount((new QueryWrapper<FtbPersonnelsStaffRoster>()).lambda()
                .eq(FtbPersonnelsStaffRoster::getWorkerType, "28")
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus, "305")
                .in(CollUtil.isNotEmpty(userIds), FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
        );
        dto.setPracticeNum(practiceNum);

        /**
         * 正式员工数量
         */
        Long formalNum = baseMapper.selectCount((new QueryWrapper<FtbPersonnelsStaffRoster>()).lambda()
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, "303")
                .in(CollUtil.isNotEmpty(userIds), FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
        );
        dto.setFormalNum(formalNum);


        /**
         * 试用员工数量
         */
        Long waitJoinNum = baseMapper.selectCount((new QueryWrapper<FtbPersonnelsStaffRoster>()).lambda()
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, "302")
                .in(CollUtil.isNotEmpty(userIds), FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
        );
        dto.setWaitJoinNum(waitJoinNum);

        return dto;
    }


    @Override
    public StaffHomeDto queryWorkerHomeDetail(String userId) {
        FtbPersonnelsStaffRoster entity = queryRosterInfoByUserId(userId);
        if (null == entity) {
            LambdaQueryWrapper<FtbPersonnelsStaffEmploymentApply> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getUserId,userId);
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getEnabledMark, 0);
            queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getIsNeedCheck, 0);
            queryWrapper.notIn(FtbPersonnelsStaffEmploymentApply::getCheckStatus, 2);
            queryWrapper.last("limit 1");
            FtbPersonnelsStaffEmploymentApply one = staffEmploymentApplyService.getOne(queryWrapper);
            if(Objects.nonNull(one)){
                throw new RuntimeException("该员工未办理入职，暂无员工档案");
            }
            throw new RuntimeException("花名册数据不存在");
        }
        StaffHomeDto dto = BeanUtil.copyProperties(entity, StaffHomeDto.class);
        // 补充工作状态转移
        UserEntity userEntity = personnelOrgUtils.queryUserInfo(dto.getCurrReportsTo());
        if (null != userEntity) {
            dto.setCurrReportsToName(userEntity.getRealName());
        }
        if (entity.getWorkerStatus().equals("305")) {
            // 如果员工离职 取离职档案信息
            LambdaQueryWrapper<FtbPersonnelsStaffArchivesHistory> archivesHistoryLambdaQueryWrapper = new LambdaQueryWrapper<FtbPersonnelsStaffArchivesHistory>()
                    .eq(FtbPersonnelsStaffArchivesHistory::getUserId, userId)
                    .eq(FtbPersonnelsStaffArchivesHistory::getEnabledMark, 1)
                    .last("limit 1");
            FtbPersonnelsStaffArchivesHistory archivesHistory = staffArchivesHistoryMapper.selectOne(archivesHistoryLambdaQueryWrapper);
            if (null != archivesHistory) {
                List<FormTypeDto> list = JSONUtil.toList(archivesHistory.getArchives(), FormTypeDto.class);
                encapsulationParameters(list, dto);
            }
        } else {
            // 补充直属主管
            //补充dataform数据
            List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryFormFieldValueList(entity.getPhone(), entity.getId());
            personnelOrgUtils.fillRosterDtoData(dto, formDataList, true);
        }

        List<WorkerGroupDataDto> list = personnelOrgUtils.getUserOrgBoundInfo(dto.getUserId());
        dto.setOrgList(list);
        if (CollUtil.isNotEmpty(list)) {
            WorkerGroupDataDto groupDataDto = list.stream().filter(WorkerGroupDataDto::getIsDefault).findFirst().orElse(new WorkerGroupDataDto());
            dto.setReportsTo(groupDataDto.getReportsTo());
            dto.setReportsToName(groupDataDto.getReportsToName());
            dto.setCurrOrg(groupDataDto.getAffiliatedOrg());
            dto.setCurrOrgName(groupDataDto.getAffiliatedOrgName());
            dto.setCurrPosition(groupDataDto.getAffiliatedPosition());
            dto.setCurrPositionName(groupDataDto.getAffiliatedPositionName());
            dto.setCurrRank(groupDataDto.getAffiliatedRank());
            dto.setCurrRankName(groupDataDto.getAffiliatedRankName());
            dto.setCurrReportsTo(groupDataDto.getReportsTo());
            dto.setCurrReportsToName(groupDataDto.getReportsToName());
            dto.setCurrGroupName(groupDataDto.getStoreTeamName());
            dto.setCurrGroupId(groupDataDto.getStoreTeamId());
        }
        if (StrUtil.isNotBlank(dto.getBirthday())) {
            Date dateBirthday = DateUtil.parse(dto.getBirthday());
            long age = DateUtil.betweenYear(dateBirthday, DateUtil.date(), false);
            dto.setAge(Long.toString(age));
        } else {
            dto.setAge("0");
        }
        List<FtbPersonnelsSalaryInfo> ftbPersonnelsSalaryInfos = personnelSalaryServiceImpl.innerGetTheCurrentPersonSSalary(entity, "", "");
        if (CollectionUtil.isNotEmpty(ftbPersonnelsSalaryInfos)) {
            ftbPersonnelsSalaryInfos.stream()
                    .filter(item -> item.getFSetValue().matches("^\\d+(\\.\\d+)?$"))
                    .map(item ->
                            BigDecimal.valueOf(Double.parseDouble(item.getFSetValue()))).reduce(BigDecimal::add)
                    .ifPresentOrElse(item ->
                                    dto.setCurrSalary(item.setScale(2, BigDecimal.ROUND_HALF_UP)),
                            () -> dto.setCurrSalary(BigDecimal.ZERO));

        }
        FtbPersonnelsStaffRosterDto.changeEscape(dto);
        return dto;
    }

    /**
     * 数据封装
     *
     * @param list
     * @param dto
     */
    private void encapsulationParameters(List<FormTypeDto> list, StaffHomeDto dto) {
        FormTypeDto formTypeDto = list.stream().filter(vo -> "1".equals(vo.getId())).findFirst().orElse(null);
        if (formTypeDto == null) return;
        List<GroupFieldDataDto> fieldDataDtoList = formTypeDto.getGroupFieldDataDtoList();
        fieldDataDtoList.forEach(item -> {
            FormFieldDto formFieldDto = item.getFormFieldDto();
            if ("idCardNum".equals(formFieldDto.getId())) {
                dto.setIdCardNum(formFieldDto.getUserValue());
            } else if ("workerSex".equals(formFieldDto.getId())) {
                dto.setWorkerSex(formFieldDto.getUserValueLable());
            } else if ("birthday".equals(formFieldDto.getId())) {
                dto.setBirthday(formFieldDto.getUserValue());
            }
        });

    }

    @Override
    public FtbPersonnelsStaffRosterDto getInfo(String id) {
        FtbPersonnelsStaffRoster entity = queryRosterAndCheckById(id);

        FtbPersonnelsStaffRosterDto dto = BeanUtil.copyProperties(entity, FtbPersonnelsStaffRosterDto.class);
        //补充组织 岗位 职等 信息 推荐人、推荐门店
        personnelOrgUtils.fillCurrOrgName(Collections.singletonList(dto));
        personnelOrgUtils.fillCurrPositionName(Collections.singletonList(dto));
        personnelOrgUtils.fillCurrRankName(Collections.singletonList(dto));
        fillContractTypeName(Collections.singletonList(dto));
        UserEntity userEntity = personnelOrgUtils.queryUserInfo(dto.getCurrReportsTo());
        if (null != userEntity) {
            dto.setCurrReportsToName(userEntity.getRealName());
        }
        //补充dataform数据
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryFormFieldValueList(entity.getPhone(), entity.getId());
        personnelOrgUtils.fillRosterDtoData(dto, formDataList, true);

        List<WorkerGroupDataDto> list = personnelOrgUtils.getUserOrgBoundInfo(dto.getUserId());
        dto.setOrgList(list);
        //兼容老数据
        //dealCurrOrgInfo(list, dto);

        //绑定的考勤组信息
        attendanceGroupService.getAttendanceUserGroup(List.of(entity.getUserId())).stream().findFirst().ifPresent(group -> {
            dto.setAttendanceGroupName(group.getGroupName());
        });
        return dto;

    }

    /**
     * 查询未填写入职登记表的用户
     *
     * @return
     */

    @Override
    public List<StaffRosterInfoDto> queryNoSubmitForm() {


        List<StaffRosterInfoDto> retList = new ArrayList<>();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .eq(FtbPersonnelsStaffRoster::getIsSubmitForm, 0)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(rosterList)) {
            return retList;
        }
        retList = BeanUtil.copyToList(rosterList, StaffRosterInfoDto.class);
        return retList;
    }

    /**
     * 查询健康证到期的人
     *
     * @param days   天数
     * @param months 月数
     * @return
     */
    @Override
    public List<StaffRosterInfoDto> queryHealthExpire(Long days, Long months) {
        if (days == null && months == null) {
            return new ArrayList<>();
        }
        List<StaffRosterInfoDto> retList = new ArrayList<>();
        Map<String, FtbPersonnelsStaffRegistrationFormData> expireFormDataMap = new HashMap<>();
        //查询并检测是否过期
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryHasHealthExpire();

        if (CollectionUtil.isNotEmpty(formDataList)) {
            for (FtbPersonnelsStaffRegistrationFormData formData : formDataList) {
                if (StringUtils.isEmpty(formData.getValue()) || StringUtils.isEmpty(formData.getRosterId())) {
                    continue;
                }
                // 将目标日期字符串解析为日期对象
                Date targetDate = DateUtil.parse(formData.getValue());
                // 获取当前日期
                Date currentDate = DateUtil.beginOfDay(DateUtil.date());
                // 判断目标日期是否尚未到来,未到来才提醒
                if (targetDate.after(currentDate)) {

                    if (days != null && months == null) {
                        // 计算距离现在还有多少天
                        long daysDiff = DateUtil.betweenDay(currentDate, targetDate, false);
                        if (daysDiff == days) {
                            expireFormDataMap.put(formData.getRosterId(), formData);
                        }
                    } else if (days == null) {
                        // 获取*个月的日期
                        Date nextMonth = DateUtil.offsetMonth(currentDate, months.intValue());
                        if (DateUtil.isSameDay(nextMonth, targetDate)) {
                            expireFormDataMap.put(formData.getRosterId(), formData);
                        }
                    } else {
                        // 计算距离现在还有多少天
                        long daysDiff = 0;
                        try {
                            daysDiff = DateUtil.betweenDay(currentDate, targetDate, false);
                        } catch (Exception e) {
                            log.error("健康证,计算距离现在还有多少天异常currentDate[{}],targetDate[{}], RosterId[{}]", currentDate, targetDate, formData.getRosterId());
                        }
                        if (daysDiff == days) {
                            expireFormDataMap.put(formData.getRosterId(), formData);
                        }
                        // 月
                        Date nextMonth = DateUtil.offsetMonth(currentDate, months.intValue());
                        if (DateUtil.isSameDay(nextMonth, targetDate)) {
                            expireFormDataMap.put(formData.getRosterId(), formData);
                        }
                    }

                } else {
                    if (days != null && months == null) {
                        if (days == 0L) {
                            // 计算距离现在还有多少天
                            long daysDiff = DateUtil.betweenDay(currentDate, targetDate, false);
                            if (daysDiff == days) {
                                expireFormDataMap.put(formData.getRosterId(), formData);
                            }
                        }
                    } else if (days == null) {
                        if (months == 0L) {
                            // 获取*个月的日期
                            Date nextMonth = DateUtil.offsetMonth(currentDate, months.intValue());
                            if (DateUtil.isSameDay(nextMonth, targetDate)) {
                                expireFormDataMap.put(formData.getRosterId(), formData);
                            }
                        }
                    }
                }
            }
        }

        //查询过期的用户信息
        if (!expireFormDataMap.isEmpty()) {
            //获取花名册用户ID
            List<String> rosterIds = expireFormDataMap.keySet().stream().collect(Collectors.toList());
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                    .in(FtbPersonnelsStaffRoster::getId, rosterIds)
                    .notIn(FtbPersonnelsStaffRoster::getWorkerStatus, "305")
                    .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
            List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
            if (CollectionUtil.isNotEmpty(rosterList)) {
                retList = BeanUtil.copyToList(rosterList, StaffRosterInfoDto.class);
                for (StaffRosterInfoDto staffRosterInfoDto : retList) {
                    FtbPersonnelsStaffRegistrationFormData ftbPersonnelsStaffRegistrationFormData = expireFormDataMap.get(staffRosterInfoDto.getId());
                    if (null != ftbPersonnelsStaffRegistrationFormData) {
                        staffRosterInfoDto.setEndHealthDate(ftbPersonnelsStaffRegistrationFormData.getValue());
                    }
                }
            }
        }
        return retList;
    }


    /**
     * 获取今日的日期 去掉 时分秒
     *
     * @return
     */
    private Date getTodayDate() {
        Calendar calendar = Calendar.getInstance();
        // 设置时间为零点零分零秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 获取调整后的时间
        return calendar.getTime();
    }


    @Override
    public ActionResult<PageListVO<PartUserInfoVoAndWorkerNo>> getPartUserInfoPage(UserQueryDto queryDto) {
        ActionResult<PageListVO<PartUserInfoVoAndWorkerNo>> ret = new ActionResult<>();
        PageListVO<PartUserInfoVoAndWorkerNo> retPage = new PageListVO<>();

        ActionResult<PageListVO<PartUserInfoVo>> partUserInfoPage = personnelOrgUtils.getPartUserInfoPage(queryDto);
        ret.setData(retPage);
        ret.setCode(partUserInfoPage.getCode());
        ret.setMsg(partUserInfoPage.getMsg());
        PageListVO<PartUserInfoVo> page = partUserInfoPage.getData();
        if (null != page) {
            List<PartUserInfoVo> list = page.getList();
            retPage.setPagination(page.getPagination());
            if (CollectionUtil.isNotEmpty(list)) {
                //获取用户ID列表
                List<String> userIds = list.stream().map(PartUserInfoVo::getUserId).collect(Collectors.toList());
                LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                        .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                        .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
                List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
                //rosterList转换成userID 的map
                Map<String, FtbPersonnelsStaffRoster> rosterMap = rosterList.stream().collect(Collectors.toMap(FtbPersonnelsStaffRoster::getUserId, roster -> roster));

                List<PartUserInfoVoAndWorkerNo> partUserInfoVoAndWorkerNos = BeanUtil.copyToList(list, PartUserInfoVoAndWorkerNo.class);
                for (PartUserInfoVoAndWorkerNo partUserInfoVoAndWorkerNo : partUserInfoVoAndWorkerNos) {
                    FtbPersonnelsStaffRoster roster = rosterMap.get(partUserInfoVoAndWorkerNo.getUserId());
                    if (null != roster) {
                        partUserInfoVoAndWorkerNo.setWorkerNo(roster.getWorkerNo());
                        partUserInfoVoAndWorkerNo.setSystemWokerId(roster.getSystemWokerId());
                    }
                }
                retPage.setList(partUserInfoVoAndWorkerNos);

            }
        }
        return ret;
    }


    /**
     * 登出
     *
     * @param tenantCode 租户编码
     * @param userId     用户id
     */
    @Override
    public void logout(String tenantCode, String userId) {
        String loginId = tenantCode + ":" + userId;
        log.error("离职推出，loginId={}", loginId);
        StpUtil.logout(loginId);
    }

    /**
     * 发送入职登记表邀请消息
     *
     * @param userId 目标用户
     * @return 执行位置
     */
    @Override
    public Boolean sendInvitationInformation(String userId) {
        //获取邀请
        LambdaQueryWrapper<FtbPersonnelsStaffEmploymentApply> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPersonnelsStaffEmploymentApply::getUserId, userId);
        FtbPersonnelsStaffEmploymentApply one = staffEmploymentApplyService.getOne(queryWrapper);
        UserInfo userInfo = UserProvider.getUser();
        String currJoinUrl = joinUrl + "&phone=" + one.getPhone();
        String storeCode = personnelOrgUtils.queryCodeForTenantId(userInfo.getTenantId());
        UserAndLinkDTO userAndLinkDTO = new UserAndLinkDTO(
                userId,
                String.format(currJoinUrl, userInfo.getTenantId(), storeCode)
        );
        // 不需要邀请填写
        // imMessageService.inviteToJoin(List.of(userAndLinkDTO));

        return true;
    }

    /**
     * APP端修改用户基本信息【头像 姓名 化名】 同步给组织架构
     *
     * @param userId 用户id
     * @param dto
     */
    @Override
    @Transactional
    public void updateBaseUserInfo(String userId, EditUserBaseInfoDto dto) {
        FtbPersonnelsStaffRoster rosterEntity = queryRosterInfoByUserId(userId);
        String name = dto.getName();
        String flowerName = dto.getFlowerName();
        String headLogo = dto.getHeadLogo();

        if(rosterEntity == null){
           updateNotExistRoster(userId, dto);
           return;
        }
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = new ArrayList<>();
        FtbPersonnelsStaffRoster saveRoster = new FtbPersonnelsStaffRoster();
        saveRoster.setId(rosterEntity.getId());
        SaveUserManagerAddDTO saveUserManagerAddDTO = new SaveUserManagerAddDTO();
        saveUserManagerAddDTO.setUserId(rosterEntity.getUserId());

        if (StringUtils.isNotEmpty(name)) {
            saveUserManagerAddDTO.setRealName(name);
            saveRoster.setName(name);
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setRosterId(rosterEntity.getId());
            formData.setPhone(rosterEntity.getPhone());
            formData.setFormTypeId("1");
            formData.setFormFieldId("workerName");
            formData.setValue(name);
            formDataList.add(formData);
        }
        if (StringUtils.isNotEmpty(headLogo)) {
            saveUserManagerAddDTO.setHeadIcon(headLogo);
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setRosterId(rosterEntity.getId());
            formData.setPhone(rosterEntity.getPhone());
            formData.setFormTypeId("1");
            formData.setFormFieldId("headLogo");
            List<String> headList = new ArrayList<>();
            headList.add(headLogo);
            formData.setValue(JSONUtil.toJsonStr(headList));
            formDataList.add(formData);
        }
        if (StringUtils.isNotEmpty(flowerName)) {
            saveUserManagerAddDTO.setNickName(flowerName);
            FtbPersonnelsStaffRegistrationFormData formData = new FtbPersonnelsStaffRegistrationFormData();
            formData.setRosterId(rosterEntity.getId());
            formData.setPhone(rosterEntity.getPhone());
            formData.setFormTypeId("1");
            formData.setFormFieldId("flowerName");
            formData.setValue(flowerName);
            formDataList.add(formData);
        }
        //修改花名册
        if (StringUtils.isNotEmpty(name)) {
            baseMapper.updateById(saveRoster);
        }

        //修改花名册附件信息
        List<FtbPersonnelsStaffRegistrationFormData> addFormDataList = new ArrayList<>();
        List<FtbPersonnelsStaffRegistrationFormData> editFormDataList = new ArrayList<>();
        for (FtbPersonnelsStaffRegistrationFormData item : formDataList) {
            FtbPersonnelsStaffRegistrationFormData oldFormData = registrationFormDataService.queryOneFieldForFieldId(item.getRosterId(), item.getFormFieldId());
            if (null != oldFormData) {
                item.setId(oldFormData.getId());
                editFormDataList.add(item);
            } else {
                addFormDataList.add(item);
            }
        }
        if (CollectionUtil.isNotEmpty(addFormDataList)) {
            registrationFormDataService.saveBatch(addFormDataList);
        }

        if (CollectionUtil.isNotEmpty(editFormDataList)) {
            registrationFormDataService.updateBatchById(editFormDataList);
        }

        //同步信息permiss
        personnelOrgUtils.sysTenantAccountBase(saveUserManagerAddDTO);
        //同步平台
        if (StringUtils.isNotEmpty(headLogo)) {
            personnelOrgUtils.sysUserHeadLog(rosterEntity.getUserId(), headLogo);
        }


    }

    /**
     * 修改用户未到花名册的情况
     * @param userId 用户id
     * @param dto 请求对象
     */
    private void updateNotExistRoster(String userId, EditUserBaseInfoDto dto) {
        SaveUserManagerAddDTO saveUserManagerAddDTO = new SaveUserManagerAddDTO();
        saveUserManagerAddDTO.setUserId(userId);
        if (StringUtils.isNotEmpty(dto.getName())) {
            saveUserManagerAddDTO.setRealName(dto.getName());
        }
        if (StringUtils.isNotEmpty(dto.getHeadLogo())) {
            saveUserManagerAddDTO.setHeadIcon(dto.getHeadLogo());
        }
        if (StringUtils.isNotEmpty(dto.getFlowerName())) {
            saveUserManagerAddDTO.setNickName(dto.getFlowerName());
        }
        //同步信息permiss
        personnelOrgUtils.sysTenantAccountBase(saveUserManagerAddDTO);
        //同步平台
        if (StringUtils.isNotEmpty(dto.getHeadLogo())) {
            personnelOrgUtils.sysUserHeadLog(userId, dto.getHeadLogo());
        }
    }

    /**
     * 根据提供的用户id 查询用户是否离职
     *
     * @param userIds 用户id集合
     * @return
     */
    @Override
    public List<FtbPersonnelsStaffRosterDto> queryDepartUser(List<String> userIds) {
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, StaffWorkerStatus.RESIGNED.getCode());
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(rosterList)) {
            return Collections.emptyList();
        }
        return BeanUtil.copyToList(rosterList, FtbPersonnelsStaffRosterDto.class);
    }

    @Override
    public List<StaffRosterSimpleBaseInfoDto> queryUserBaseInfoAndOrgAndPosAndRank(List<String> userIds, String tenantId) {
        List<FtbPersonnelsStaffRoster> rosterList = this.lambdaQuery()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getName,
                        FtbPersonnelsStaffRoster::getPhone, FtbPersonnelsStaffRoster::getWorkerStatus)
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
                .orderByAsc(FtbPersonnelsStaffRoster::getCreatorTime)
                .list();
        List<FtbPersonnelsStaffRegistrationFormData> formDataList = CollUtil.isNotEmpty(rosterList) ? registrationFormDataService.lambdaQuery()
                .in(FtbPersonnelsStaffRegistrationFormData::getRosterId, rosterList.stream().map(FtbPersonnelsStaffRoster::getId).collect(Collectors.toList()))
                .in(FtbPersonnelsStaffRegistrationFormData::getFormFieldId, "flowerName", "headLogo")
                .list() : Lists.newArrayList();
        Map<String, List<FtbPersonnelsStaffRegistrationFormData>> formDataMap = CollUtil.isNotEmpty(formDataList) ?
                formDataList.stream().collect(Collectors.groupingBy(FtbPersonnelsStaffRegistrationFormData::getRosterId)) : new HashMap<>();

        List<StaffRosterSimpleBaseInfoDto> retList = personnelOrgUtils.queryUserBaseInfoAndOrgAndPosAndRank(userIds, tenantId);
        Map<String, StaffRosterSimpleBaseInfoDto> userOrgMap = CollUtil.isNotEmpty(retList) ?
                retList.stream().collect(Collectors.toMap(StaffRosterSimpleBaseInfoDto::getUserId, a -> a, (k1, k2) -> k1)) : new HashMap<>();
        return CollUtil.isNotEmpty(rosterList) ? rosterList.stream().map(roster -> {
            StaffRosterSimpleBaseInfoDto baseInfoDto = StaffRosterSimpleBaseInfoDto.builder().build();
            BeanUtil.copyProperties(roster, baseInfoDto);
            //设置组织架构的信息
            if (userOrgMap.containsKey(roster.getUserId()) && CollUtil.isNotEmpty(userOrgMap.get(roster.getUserId()).getInfoList())) {
                baseInfoDto.setInfoList(userOrgMap.get(roster.getUserId()).getInfoList());
            }
            //设置头像、花名
            if (formDataMap.containsKey(roster.getId())) {
                List<FtbPersonnelsStaffRegistrationFormData> userFormDataList = formDataMap.get(roster.getId());
                for (FtbPersonnelsStaffRegistrationFormData item : userFormDataList) {
                    if ("flowerName".equals(item.getFormFieldId())) {
                        baseInfoDto.setFlowerName(item.getValue());
                    } else if ("headLogo".equals(item.getFormFieldId())) {
                        baseInfoDto.setHeadLogo(personnelOrgUtils.convertHeadLogo(item.getValue()));
                    }
                }
            }
            return baseInfoDto;
        }).collect(Collectors.toList()) : Lists.newArrayList();
    }

    /**
     * 根据用户ID查询所属门店负责人信息
     *
     * @param userIds 用户ID集合
     * @return
     */
    @Override
    public ShopManagerUserDto queryShopManagerUser(List<String> userIds) {
        List<StoreUserRelationVo> list = personnelOrgUtils.queryStoreManagerForUserId(userIds);
        Map<String, Set<String>> map = new HashMap<>();
        for (StoreUserRelationVo vo : list) {
            Set<String> userSet = map.get(vo.getStoreManagerUserId());
            if (CollectionUtil.isEmpty(userSet)) {
                userSet = new HashSet<>();
            }
            userSet.add(vo.getUserId());
            map.put(vo.getStoreManagerUserId(), userSet);
        }
        ShopManagerUserDto dto = new ShopManagerUserDto();
        dto.setMap(map);
        return dto;
    }

    @Override
    public void timingAlertTrialJob(String tenantId) {
        Date now = new Date();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, StaffWorkerStatus.PRE_TRIAL.getCode())
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            List<FtbPersonnelsStaffRoster> alertList = new ArrayList<>();
            for (FtbPersonnelsStaffRoster roster : rosterList) {
                Date today = PersonnelStaffUtils.getTodayDate();
                Date endDate = DateUtil.offsetDay(roster.getActualStartDate(), roster.getTrialJobDay() - 1);
                if (now.before(endDate)) {
                    long betweenDay = DateUtil.betweenDay(endDate, today, false);
                    if (betweenDay == 1) {
                        //刚刚相差1天 ，给办理入职 权限人员 推送消息
                        alertList.add(roster);
                    }
                } else if (personnelOrgUtils.dateToString(today, "yyyy-MM-dd").equals(personnelOrgUtils.dateToString(endDate, "yyyy-MM-dd"))) {

                } else {
                }
            }
            if (CollectionUtil.isNotEmpty(alertList)) {
                sendTrialAlert(tenantId, alertList);
            }
        }
    }

    @Override
    public void timingUpdateTrialJob(String tenantId) {
        Date now = new Date();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .eq(FtbPersonnelsStaffRoster::getWorkerStatus, StaffWorkerStatus.PRE_TRIAL.getCode())
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            List<FtbPersonnelsStaffRoster> alertList = new ArrayList<>();
            for (FtbPersonnelsStaffRoster roster : rosterList) {
                Date today = PersonnelStaffUtils.getTodayDate();
                Date endDate = DateUtil.offsetDay(roster.getActualStartDate(), roster.getTrialJobDay() - 1);
                if (now.before(endDate)) {

                } else if (personnelOrgUtils.dateToString(today, "yyyy-MM-dd").equals(personnelOrgUtils.dateToString(endDate, "yyyy-MM-dd"))) {

                } else {
                    //试岗结束 进入试用期（有试用期） 直接转正（无试用期）
                    dealWithPreTrial(roster);
                }
            }

        }
    }


    @Override
    public BaseUserInfoVo getUserMoreInfoByUserId(String userId) {
        if (StrUtil.isBlank(userId)) {
            return null;
        }
        BaseUserInfoVo vo = userApi.getUserInfoById(userId);
        if (vo == null) {
            return null;
        }
        this.list(Wrappers.<FtbPersonnelsStaffRoster>lambdaQuery()
                .eq(FtbPersonnelsStaffRoster::getUserId, userId)
        ).stream().findFirst().ifPresent(roster -> {
            vo.setWorkStatus(roster.getWorkerStatus());
            vo.setWorkStatusName(StaffWorkerStatus.getWorkerStatusNameByValue(roster.getWorkerStatus()));
        });

        return vo;
    }

    private void dealWithPreTrial(FtbPersonnelsStaffRoster roster) {
        ProbationPeriodDto probationPeriodDto = queryProbationPeriod(registrationFormDataService, roster.getId());
        if (null == probationPeriodDto || probationPeriodDto.getType().equals("100")) {//没有配置试用期直接转正
            innerPreTrailChangeRegular(roster, buildStaffRegularDto(roster.getUserId()));
            return;
        }
        //有试用期，直接改成试用
        FtbPersonnelsStaffRoster updateRoster = new FtbPersonnelsStaffRoster();
        updateRoster.setUserId(roster.getUserId());
        updateRoster.setWorkerStatus(StaffWorkerStatus.TRIAL.getCode());
        updateRoster.setId(roster.getId());
        baseMapper.updateById(updateRoster);
        registrationFormDataService.updateForOneField(roster.getId(), roster.getPhone(), "workerStatus", StaffWorkerStatus.TRIAL.getCode());


    }

    private StaffRegularDto buildStaffRegularDto(String userId) {
        List<WorkerGroupDataDto> workerGroupDataDtoList = personnelOrgUtils.getUserOrgBoundInfo(userId);
        StaffRegularDto dto = new StaffRegularDto();
        dto.setRegularDate(new Date());
        if (CollectionUtil.isNotEmpty(workerGroupDataDtoList)) {
            WorkerGroupDataDto item = workerGroupDataDtoList.get(0);
            dto.setNewOrg(item.getAffiliatedOrg());
            dto.setNewPosition(item.getAffiliatedPosition());
            dto.setNewRank(item.getAffiliatedRank());
            dto.setNewOrgName(item.getAffiliatedOrgName());
            dto.setNewPositionName(item.getAffiliatedPositionName());
            dto.setNewRankName(item.getAffiliatedRankName());
            dto.setImmediateSuperId(item.getReportsToName());
            dto.setRemarks("");
        }
        return dto;
    }

    /**
     * 发送试岗消息
     *
     * @param alertList
     */
    private void sendTrialAlert(String tenantId, List<FtbPersonnelsStaffRoster> alertList) {
        Map<String, List<String>> userToOrgMap = new HashMap<>();//用户->组织id，每个用户拥有的组织
        Map<String, FtbPersonnelsStaffRoster> userMap = new HashMap<>();//用户ID ->用户详情
        for (FtbPersonnelsStaffRoster roster : alertList) {
            userMap.put(roster.getUserId(), roster);
            Map<String, List<WorkerGroupDataDto>> map = personnelOrgUtils.getUserOrgBoundInfoForUserListAndTenantId(List.of(roster.getUserId()), tenantId, false);
            List<WorkerGroupDataDto> workerGroupDataDtoList = map.get(roster.getUserId());
            List<String> orgList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(workerGroupDataDtoList)) {
                for (WorkerGroupDataDto item : workerGroupDataDtoList) {
                    orgList.add(item.getAffiliatedOrg());
                }
            }
            userToOrgMap.put(roster.getUserId(), orgList);

        }
        if (CollectionUtil.isEmpty(userToOrgMap)) {
            return;
        }

        Map<String, Set<String>> managerUserToUserMap = new HashMap<>();//管理人员ID->对应用户列表

        for (Map.Entry<String, List<String>> entry : userToOrgMap.entrySet()) {
            String userId = entry.getKey(); //用户ID
            List<String> orgIds = entry.getValue();//组织ID
            if (CollectionUtil.isEmpty(orgIds)) {
                continue;
            }
            for (String orgId : orgIds) {
                List<String> powderUserIds = personnelPerUtils.obtainPersonnelUserIdDataPermissionsByOrgId(orgId, userId, tenantId);
                log.info("用户ID={},组织ID={},组织下用户ID={}", userId, orgId, JSONUtil.toJsonStr(powderUserIds));
                if (CollectionUtil.isNotEmpty(powderUserIds)) {
                    for (String powderUserId : powderUserIds) {
                        Set<String> set = managerUserToUserMap.get(powderUserId);
                        if (CollectionUtil.isEmpty(set)) {
                            set = new HashSet<>();
                        }
                        set.add(userId);
                        managerUserToUserMap.put(powderUserId, set);
                    }
                }
            }
        }
        //发送消息
        for (String managerUserId : managerUserToUserMap.keySet()) {
            Set<String> currUserSet = managerUserToUserMap.get(managerUserId);//用户ID
            if (CollectionUtil.isEmpty(currUserSet)) {
                continue;
            }

            List<String> sendUserNameList = new ArrayList<>();
            for (String userId : currUserSet) {
                FtbPersonnelsStaffRoster roster = userMap.get(userId);
                if (null != roster) {
                    sendUserNameList.add(roster.getName());
                }
            }
            if (CollectionUtil.isEmpty(sendUserNameList)) {
                continue;
            }
            personnelPreTrailIMUtils.sendMsg(tenantId, List.of(managerUserId), sendUserNameList);
        }
    }


    @Override
    @Transactional
    public void updateSignSeparation(String userId, Integer status) {

        FtbPersonnelsStaffRoster roster = queryRosterInfoByUserId(userId);
        if (null == roster) {
            throw new RuntimeException("用户不存在");
        }
        FtbPersonnelsStaffRoster updateEntity = new FtbPersonnelsStaffRoster();
        updateEntity.setIsSignSeparation(status);
        updateEntity.setId(roster.getId());
        baseMapper.updateById(updateEntity);

        if (status == 1 && roster.getWorkerStatus().equals(StaffWorkerStatus.PENDING_RESIGNATION.getCode())) {
            if (roster.getIsTrialFail() == 1) {
                List<WorkerGroupDataDto> workerGroupDataDtoList = personnelOrgUtils.getUserOrgBoundInfo(userId);
                StaffTravlFailDto dto = new StaffTravlFailDto();
                dto.setRemarks(roster.getTrialFail());
                dto.setList(workerGroupDataDtoList);
                dto.setFailDate(new Date());
                dto.setStaffWorkerStatus(StaffWorkerStatus.RESIGNED);
                innerTravelFail(userId, dto);

                FtbjobTrialRejectedDTO ftbjobTrialRejectedDTO = new FtbjobTrialRejectedDTO();
                ftbjobTrialRejectedDTO.setReasonsForJobRejection(dto.getRemarks());
                ftbjobTrialRejectedDTO.setUserId(userId);
                ftbjobTrialRejectedDTO.setSystemWokerId(roster.getSystemWokerId());
                ftbjobTrialRejectedDTO.setPhoneNumber(roster.getPhone());
                ftbjobTrialRejectedDTO.setUserName(roster.getName());
                ftbjobTrialRejectedDTO.setJobNumber(roster.getWorkerNo());
                ftbjobTrialRejectedDTO.setDateOfEntry(roster.getCreatorTime());
                ftbjobTrialRejectedDTO.setResignationDate(new Date());
                ftbjobTrialRejectedDTO.setOrganizationInfo(workerGroupDataDtoList);
                ftbjobTrialRejectedDTO.setOrgId(roster.getCurrOrg());
                ftbjobTrialRejectedDTO.setEntryPostId(roster.getCurrPosition());
                ftbjobTrialRejectedDTO.setEntryGradeId(roster.getCurrRank());
                turnoverManagementService.jobTrialRejected(ftbjobTrialRejectedDTO);
            } else {
                turnoverManagementService.userHasSignedASeparationAgreement(userId, status);
            }
        } else {
            turnoverManagementService.userHasSignedASeparationAgreement(userId, status);
        }
    }


    /**
     * 检查合同到期并修改状态
     *
     * @param tenantId
     */
    @Override
    public void timingCheckContractOverTime(String tenantId) {
        Date now = new Date();
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaQueryWrapper<FtbPersonnelsStaffRoster>()
                .select(FtbPersonnelsStaffRoster::getId, FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getPhone, FtbPersonnelsStaffRoster::getContractStatus)
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus, "305")
                .eq(FtbPersonnelsStaffRoster::getContractStatus, FContractSignStatus.SIGNED.getCode())
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = baseMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(rosterList)) {
            //获取花名册ID列表
            List<String> rosterIds = rosterList.stream().map(FtbPersonnelsStaffRoster::getId).collect(Collectors.toList());
            List<FtbPersonnelsStaffRegistrationFormData> formDataList = registrationFormDataService.queryListForRosterIdAndField(rosterIds, List.of("contractDate"));
            if (CollectionUtil.isEmpty(formDataList)) {
                return;
            }
            for (FtbPersonnelsStaffRegistrationFormData formData : formDataList) {
                if (StringUtils.isEmpty(formData.getValue())) {
                    continue;
                }
                Date date = personnelOrgUtils.stringDateToDate(formData.getValue());

                if (now.after(date)) {//当前时间在date之后
                    FtbPersonnelsStaffRoster updateRoster = new FtbPersonnelsStaffRoster();
                    updateRoster.setId(formData.getRosterId());
                    updateRoster.setContractStatus(FContractSignStatus.EXPIRED.getCode());
                    baseMapper.updateById(updateRoster);
                    registrationFormDataService.updateForOneField(formData.getRosterId(), formData.getPhone(), "contractStatus", FContractSignStatus.EXPIRED.getDescription());
                }

            }

        }
    }

    @Override
    public Boolean canUpdateRealName() {
        //花名册能够修改真实姓名(0-可以修改 1-不可修改)
        String flag = baseMapper.canUpdateRealName();
        if (StringUtils.isEmpty(flag)) {
            return true;
        }
        if (flag.equals("1")) {
            return false;
        }
        return true;
    }

    @Override
    public Map<String, Object> getInfoForUserIdOneField(String field, String userId) {
        Map<String, Object> retMap = new HashMap<>();

        FtbPersonnelsStaffRoster roster = queryRosterInfoByUserId(userId);
        if (null == roster) {
            throw new RuntimeException("用户不存在");
        }
        StaffHomeDto dto = BeanUtil.copyProperties(roster, StaffHomeDto.class);
        fillContractTypeName(Collections.singletonList(dto));
        // 补充工作状态转移
        FtbPersonnelsStaffRosterDto.changeEscape(dto);
        BeanUtil.beanToMap(dto, retMap, false, false);
        if (mainTableField.contains(field)) {
            return retMap;
        }
        if (extTableField.contains(field)) {
            if ("userRoleList".equals(field)) {
                List<SaffRoleDto> saffRoleDtos = personnelOrgUtils.queryRoleListForUserId(roster.getUserId());
                retMap.put("userRoleList", saffRoleDtos);
                return retMap;
            }
            if ("orgList".equals(field) || "currReportsTo".equals(field) || "currReportsToName".equals(field)) {
                List<WorkerGroupDataDto> list = personnelOrgUtils.getUserOrgBoundInfo(roster.getUserId());
                retMap.put("orgList", list);
                if (CollUtil.isNotEmpty(list)) {
                    WorkerGroupDataDto groupDataDto = list.stream().filter(user -> user.getIsDefaultOrganize() && user.getIsDefaultPosition()).findFirst().orElse(new WorkerGroupDataDto());
                    retMap.put("currReportsTo", groupDataDto.getReportsTo());
                    retMap.put("currReportsToName", groupDataDto.getReportsToName());
                }
                return retMap;
            }

            if ("attendanceGroup".equals(field) || "attendanceGroupName".equals(field)) {
                List<AttendanceUserGroupVo> attendanceUserGroupList = personnelOrgUtils.queryAttendanceGroup(roster.getUserId());
                List<String> groupName = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(attendanceUserGroupList)) {
                    //stram获取考勤组名称
                    for (AttendanceUserGroupVo attendanceUserGroupVo : attendanceUserGroupList) {
                        groupName.add(attendanceUserGroupVo.getGroupName());
                    }
                }
                retMap.put("attendanceGroupName", String.join(",", groupName));
                return retMap;
            }
            if ("currSalary".equals(field)) {
                List<FtbPersonnelsSalaryInfo> ftbPersonnelsSalaryInfos = personnelSalaryServiceImpl.innerGetTheCurrentPersonSSalary(roster, "", "");
                if (CollectionUtil.isNotEmpty(ftbPersonnelsSalaryInfos)) {
                    BigDecimal bigDecimal = ftbPersonnelsSalaryInfos.stream()
                            .filter(item -> item.getFSetValue().matches("^\\d+(\\.\\d+)?$"))
                            .map(v -> BigDecimal.valueOf(Double.parseDouble(v.getFSetValue()))).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                    retMap.put("currSalary", bigDecimal);
                    return retMap;
                }
            }
            //查询框考勤组信息
        }
        FtbPersonnelsRegistrationFormField formFieldDto = registrationFormFieldService.queryOneField(field);
        if (formFieldDto == null) {
            retMap.put(field, null);
            return retMap;
        }
        FtbPersonnelsStaffRegistrationFormData formFieldValue = registrationFormDataService.queryOneFieldForFieldId(roster.getId(), field);
        if (formFieldValue == null) {
            retMap.put(field, null);
            return retMap;
        }

        String formValueStr = formFieldValue.getValue();
        retMap.put(field, formFieldValue.getValue());
        if ("headLogo".equals(formFieldDto.getId())) {
            List<String> headLogoList = personnelOrgUtils.parseHeadLogo(formFieldValue.getValue());
            retMap.put("headLogo", headLogoList.get(0));
        } else if ("probationPeriod".equals(formFieldDto.getId())) {
            if (StringUtils.isNotEmpty(formFieldValue.getValue()) && formFieldValue.getValue().startsWith("{")) {
                ProbationPeriodDto bean = JSONUtil.toBean(formFieldValue.getValue(), ProbationPeriodDto.class);
                retMap.put("probationPeriod", bean.getType());
                retMap.put("probationPeriodDay", bean.getDays());
                retMap.put("probationPeriodDayName", personnelOrgUtils.convertProbationPeriod(bean));
            }
        } else if (formFieldDto.getType() == 2 || formFieldDto.getType() == 3) {
            List<FtbPersonnelsRegistrationFormFieldOption> optionList = fieldOptionService.queryOptionsByFieldId(formFieldDto.getId());
            Map<String, FtbPersonnelsRegistrationFormFieldOption> optionMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(optionList)) {
                optionMap = optionList.stream().collect(Collectors.toMap(FtbPersonnelsRegistrationFormFieldOption::getId, Function.identity()));
            }

            if (StringUtils.isNotEmpty(formValueStr)) {
                FtbPersonnelsRegistrationFormFieldOption ftbPersonnelsRegistrationFormFieldOption = optionMap.get(formValueStr);
                if (ftbPersonnelsRegistrationFormFieldOption != null) {
                    retMap.put(field, ftbPersonnelsRegistrationFormFieldOption.getName());
                } else {
                    retMap.put(field, null);
                }
            }
        }
        return retMap;
    }
}
