package jnpf.personnels.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
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 io.seata.spring.annotation.GlobalTransactional;
import jnpf.attendance.AttendanceGroupApi;
import jnpf.attendance.dto.AttendanceUserGroupVo;
import jnpf.authority.utils.PermissionsEnums;
import jnpf.authority.utils.PermissionsUtils;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.base.vo.PageListVO;
import jnpf.cultivate.service.impl.FtbCultivateFileService;
import jnpf.engine.FlowTaskApi;
import jnpf.engine.entity.FlowTaskEntity;
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
import jnpf.exception.DataException;
import jnpf.model.cultivate.CultivatePage;
import jnpf.model.cultivate.dto.offline.FtbCultivateOfflineFileDTO;
import jnpf.model.cultivate.event.JnpfApplicationEvent;
import jnpf.model.cultivate.event.dto.file.FileEventDTO;
import jnpf.model.cultivate.po.FtbCultivateFile;
import jnpf.model.cultivate.vo.offline.FtbCultivateOfflineFileVO;
import jnpf.model.enums.FtbPersonnelsAuditTaskEnum;
import jnpf.model.enums.FtbPersonnelsCofigEnum;
import jnpf.model.im.UserSuccessDTO;
import jnpf.model.personnels.dto.base.PersonnelsQueryDTO;
import jnpf.model.personnels.dto.regular.FtbPersonnelsForAppQueryDTO;
import jnpf.model.personnels.dto.regular.FtbPersonnelsRegularCreateDTO;
import jnpf.model.personnels.dto.regular.FtbPersonnelsSalaryAuditDto;
import jnpf.model.personnels.dto.salary.FtbPersonnelsSalaryInfo;
import jnpf.model.personnels.dto.staff.roster.StaffHomeDto;
import jnpf.model.personnels.dto.staff.roster.StaffRegularDto;
import jnpf.model.personnels.po.FtbPersonnelsRegularManagement;
import jnpf.model.personnels.po.FtbPersonnelsSecondmentManagement;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.model.personnels.vo.app.FtbPersonnelsBubbleCountVO;
import jnpf.model.personnels.vo.regular.FtbPersonnelsRegularInfoVO;
import jnpf.model.personnels.vo.regular.FtbPersonnelsRegularManagementVO;
import jnpf.model.personnels.vo.salary.UserInfoWithSalary;
import jnpf.model.personnels.vo.task.FtbPersonnelsAuditInfoVO;
import jnpf.model.personnels.vo.task.FtbPersonnelsResult;
import jnpf.model.vo.UserSalaryHistoryVo;
import jnpf.permission.V2GradesApi;
import jnpf.permission.V2PositionApi;
import jnpf.permission.V2UserApi;
import jnpf.permission.dto.v2.grades.QueryGradeListDTO;
import jnpf.permission.dto.v2.user.QueryUserBoundDTO;
import jnpf.permission.entity.OrganizeEntity;
import jnpf.permission.entity.PositionEntity;
import jnpf.permission.model.position.PositionGradesInfoVO;
import jnpf.permission.vo.v2.grades.GradeVO;
import jnpf.permission.vo.v2.position.PositionVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.permission.vo.v2.user.UserRelationBaseVO;
import jnpf.personnels.mapper.FtbPersonnelsRegularManagementMapper;
import jnpf.personnels.service.*;
import jnpf.personnels.utils.PersonnelOrgUtils;
import jnpf.personnels.utils.PersonnelPerUtils;
import jnpf.salary.QuerySalaryApi;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import jnpf.util.context.SpringContext;
import jnpf.util.im.ImMessageNoticeUtils;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class FtbPersonnelsRegularManagementServiceImpl extends ServiceImpl<FtbPersonnelsRegularManagementMapper, FtbPersonnelsRegularManagement> implements FtbPersonnelsRegularManagementService {

    @Resource
    private FtbPersonnelsAuditRunTaskService runTaskService;

    @Resource
    private FtbCultivateFileService ftbCultivateFileService;

    @Resource
    private FtbPersonnelsAuditSubConfigService subConfigService;

    @Resource
    private FtbPersonnelsStaffRosterService staffRosterService;

    @Autowired
    V2UserApi v2UserApi;

    @Resource
    public PersonnelPerUtils personnelPerUtils;

    @Resource
    private AttendanceGroupApi attendanceGroupApi;

    @Autowired
    private V2PositionApi v2PositionApi;

    @Autowired
    private V2GradesApi v2GradesApi;

    @Autowired
    ImMessageNoticeUtils noticeUtils;

    @Autowired
    FtbPersonnelsSalaryService salaryService;

    @Autowired
    PersonnelOrgUtils personnelOrgUtils;

    @Autowired
    QuerySalaryApi querySalaryApi;

    @Autowired
    FtbPersonnelsStaffGrowthLogService logService;

    @Resource
    private PermissionHandling permissionHandling;

    @Resource
    PermissionsUtils permissionsUtils;

    @Resource
    FlowTaskApi flowTaskApi;

    @Resource
    private FtbPersonnelsSecondmentManagementService ftbPersonnelsSecondmentManagementService;
    @Override
    @Transactional
    public void cancellationOfApplicationForRectification(String id, String taskId) {
        if (StringUtils.isEmpty(id) && StringUtils.isEmpty(taskId)) {
            throw new RuntimeException("参数错误!");
        }
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(StringUtils.isNotEmpty(id),FtbPersonnelsRegularManagement::getId,id);
        queryWrapper.eq(StringUtils.isNotEmpty(taskId),FtbPersonnelsRegularManagement::getTaskInfoId,taskId);
        FtbPersonnelsRegularManagement vo = baseMapper.selectOne(queryWrapper);
        Integer transferStatus = vo.getTransferStatus();
        if (!List.of(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode(),
                FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode()).contains(transferStatus)) {
            throw new RuntimeException("该审批无法撤销!");
        }
        // 时间先清除
        logService.revocationGrowthLog(vo.getUserId(),vo.getCreatorTime());
        // 撤销
        LambdaUpdateWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaUpdate();
        // 转正金额设置为空
        wrapper.set(FtbPersonnelsRegularManagement::getTransferStatus, FtbPersonnelsAuditTaskEnum.CANCEL.getCode());
        // 手动办理将已有的taskId设置为空
        if (FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode().equals(transferStatus)) wrapper.set(FtbPersonnelsRegularManagement::getTaskInfoId, null);
        wrapper.eq(StringUtils.isNotEmpty(id),FtbPersonnelsRegularManagement::getId,id);
        wrapper.eq(StringUtils.isNotEmpty(taskId),FtbPersonnelsRegularManagement::getTaskInfoId,taskId);
        baseMapper.update(null, wrapper);
        //  同步撤销状态到花名册
        staffRosterService.cancelRegular(vo.getUserId());
        // 如果使用了薪酬模版 需要 进行数据撤销回滚
        if ("1".equals(vo.getIsAdjustSalary())) {
            // 撤销成功
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String format = sdf.format(vo.getPayrollEffectiveDate());
            salaryService.voidSalary(vo.getUserId(),format, vo.getSalaryRecordId());
        }

    }

    @Override
    @Transactional
    public void regularizationApproval(FtbPersonnelsSalaryAuditDto auditDto) {
        // 判断该员工的岗位是否在提交转正审批后发生了变更(该员工所属组织的岗位模板发生变化导致该员工的岗位发生同步变化) ;
        // 以及判断转正后目标岗位是否不存在
        FtbPersonnelsRegularManagement regularManagement = baseMapper.selectById(auditDto.getBusinessId());
        // 选择通过需要校验组织是否存在
        if ("1".equals(auditDto.getFlag()))verify(regularManagement);
        FtbPersonnelsAuditTaskEnum performReview = runTaskService.performReview(auditDto);
        LambdaUpdateWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(FtbPersonnelsRegularManagement::getTransferStatus, performReview.getCode());
        wrapper.eq(FtbPersonnelsRegularManagement::getId, auditDto.getBusinessId());
        if (StringUtils.isNotEmpty(auditDto.getIsAdjustSalary())){
            wrapper.set(FtbPersonnelsRegularManagement::getIsAdjustSalary,auditDto.getIsAdjustSalary());
        }
        if (StringUtils.isNotEmpty(auditDto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructure,auditDto.getSalaryStructure());
        }
        if ( ObjectUtil.isNotEmpty(auditDto.getSalary())){
            wrapper.set(FtbPersonnelsRegularManagement::getRegularSalary,auditDto.getSalary());
        }
        if (ObjectUtil.isNotEmpty(auditDto.getPayrollEffectiveDate())){
            wrapper.set(FtbPersonnelsRegularManagement::getPayrollEffectiveDate,auditDto.getPayrollEffectiveDate());
        }
        List<FtbPersonnelsSalaryInfo> salaryStructureList1 = auditDto.getSalaryStructureList();
        if(CollUtil.isNotEmpty(salaryStructureList1)){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructureList,
                    JSONObject.toJSONString(salaryStructureList1));
        }
        // 薪资员工自己申请的
        if(ObjectUtil.isNotEmpty(auditDto.getIsAdjustSalary())){
            if (CollUtil.isEmpty(salaryStructureList1)  && "1".equals(auditDto.getIsAdjustSalary()) ){
                throw new RuntimeException("目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
            }
            wrapper.set(FtbPersonnelsRegularManagement::getIsAdjustSalary,auditDto.getIsAdjustSalary());
        }
        if(ObjectUtil.isNotEmpty(auditDto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructure,auditDto.getSalaryStructure());
        }
        wrapper.set(StringUtils.isNotEmpty(auditDto.getReasonsForSalaryAdjustments()),
                FtbPersonnelsRegularManagement::getReasonsForSalaryAdjustments,
                auditDto.getReasonsForSalaryAdjustments());
        baseMapper.update(null, wrapper);
        if (FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.equals(performReview)) {
            // 转正员工同步
            FtbPersonnelsRegularManagement thisRegularInfo = baseMapper.selectById(auditDto.getBusinessId());
            // 成功通知
            messageNotifications(regularManagement.getUserId(), true);
            synchronizePayrollData(thisRegularInfo);
        }else if (FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.equals(performReview)){
            // 失败通知
            messageNotifications(regularManagement.getUserId(), false);
        }
    }
    /**
     * 校验岗位是否存在
     * @param management
     */
    private void verify(FtbPersonnelsRegularManagement management) {
        // 校验岗位是否还存在
        QueryUserBoundDTO checkExistByPositionDTO = new QueryUserBoundDTO();
        checkExistByPositionDTO.setOrganizeId(management.getOrgId());
        checkExistByPositionDTO.setPositionId(management.getRegularPostId());
        checkExistByPositionDTO.setGradeId(management.getRegularGradeId());
        ActionResult<List<UserRelationBaseVO>> result = v2UserApi.listUserBound(checkExistByPositionDTO);
        if (result  == null || result.getData() == null ){
            throw new RuntimeException("该员工的岗位在提交转正审批后发生了变更，无法继续审批；请选择“不通过”结束审批流程！");
        }
    }

    /**
     * 消息通知
     * @param userId
     * @param success
     */
    private void messageNotifications(String userId, boolean success) {
        UserSuccessDTO successDTO = new UserSuccessDTO();
        successDTO.setUserIds(List.of(userId));
        successDTO.setSuccess(success);
        noticeUtils.becomeRegularEmployee(List.of(successDTO));
    }

    @Override
    public PageListVO<FtbPersonnelsRegularManagementVO> pageList(PersonnelsQueryDTO dto, CultivatePage cultivatePage, Boolean export) {
        Page<FtbPersonnelsRegularManagementVO> page = cultivatePage.coverCultivatePage();
        // 超过转正时间(审批通过,超过实际转正时间,列表不显示)
//        if (!export) {
//            removeTheCorrectionReviewTimeExceeded();
//        }
        UserInfo user = UserProvider.getUser();
        if ( !user.getIsAdministrator() ) {
            // 数据权限userIds
            List<String> userIds = permissionHandling.getUserIdsByUserId(user.getUserId());
            if (userIds != null && userIds.isEmpty()) return CultivatePage.coverPageList(page);
            if (CollUtil.isNotEmpty(userIds)) {
                dto.setUserIds(userIds);
            }
        }
        List<FtbPersonnelsRegularManagementVO> regularManagementVOList  = baseMapper.queryList(dto);
        List<String> userIds = regularManagementVOList.stream().filter(item -> item.getTransferStatus() == 5).map(FtbPersonnelsRegularManagementVO::getUserId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userIds)){
            supplementalData(userIds, regularManagementVOList);
        }
        if (CollUtil.isNotEmpty(dto.getOrgIds())) {
            List<String> orgIds = dto.getOrgIds();
            regularManagementVOList = regularManagementVOList.stream()
                    .filter(v -> StringUtils.isNotEmpty(v.getOrgId()) && orgIds.contains(v.getOrgId())).collect(Collectors.toList());
        }
        regularManagementVOList.stream().filter(v->v.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode()) ||
                v.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.CANCEL.getCode())).forEach(item->{
            if (StringUtils.isNotEmpty(item.getTaskInfoId())) {
                FlowTaskEntity byTaskId = flowTaskApi.findByTaskId(item.getTaskInfoId());
                if (ObjectUtil.isNotEmpty(byTaskId) &&  user.getUserId().equals(byTaskId.getCreatorUserId())) {
                    item.setCurrentSponsor(1);
                } else {
                    item.setCurrentSponsor(0);
                }
            }
        });
        return CultivatePage.paginate(regularManagementVOList,page);
    }

    /**
     * 超过转正时间(审批通过,超过实际转正时间,列表不显示)
     */
    private void removeTheCorrectionReviewTimeExceeded() {
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPersonnelsRegularManagement::getEnableMark,0);
        List<FtbPersonnelsRegularManagement> ftbPersonnelsRegularManagements = baseMapper.selectList(queryWrapper);
        Date date = new Date();
        List<String> userIds = ftbPersonnelsRegularManagements.stream().filter(item -> item.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.NOT_PROCESSED.getCode())).map(FtbPersonnelsRegularManagement::getUserId).collect(Collectors.toList());
        Map<String, UserBoundVO> userMap = new HashMap<>();
        if (CollUtil.isNotEmpty(userIds)) {
            ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getUserPrimaryBoundBatch(userIds, null);
            if (actionResult != null || CollUtil.isNotEmpty(actionResult.getData())) {
                return;
            }
            userMap = actionResult.getData().stream()
                    .collect(Collectors.toMap(UserBoundVO::getId, Function.identity(), (k1, k2) -> k1));
        }
        // 将未办理数据实时更新最新的组织信息
        Map<String, UserBoundVO> finalUserMap = userMap;
        ftbPersonnelsRegularManagements.forEach(item -> {
            if (item.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode()) ||
                    item.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode())) {
                boolean sameDay =false;
                if (item.getActualConverDate() != null ) {
                    sameDay = isSameDay(date, item.getActualConverDate());
                }
                if (item.getActualConverDate() != null &&  (date.after(item.getActualConverDate()) || sameDay )) {
                    LambdaUpdateWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaUpdate();
                    wrapper.set(FtbPersonnelsRegularManagement::getEnableMark, 1);
                    wrapper.set(SuperBaseEntity.SuperCUDBaseEntity::getDeleteUserId,UserProvider.getUser().getUserId());
                    wrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, item.getId());
                    baseMapper.update(new FtbPersonnelsRegularManagement(), wrapper);
                }
            }
            if (  finalUserMap.containsKey(item.getUserId())  && item.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.NOT_PROCESSED.getCode())){
                FtbPersonnelsRegularManagement management = new FtbPersonnelsRegularManagement();
                UserBoundVO boundMoreInfoVO = finalUserMap.get(item.getUserId());
                // 任一一个有变化进行更新
                if ((StringUtils.isNotEmpty(boundMoreInfoVO.getOrganizeId()) && !boundMoreInfoVO.getOrganizeId().equals(item.getOrgId()))||
                        (StringUtils.isNotEmpty(boundMoreInfoVO.getOrganizeName()) && !boundMoreInfoVO.getOrganizeName().equals(item.getOrgName()))||
                        (StringUtils.isNotEmpty(boundMoreInfoVO.getPositionId()) && !boundMoreInfoVO.getPositionId().equals(item.getRegularPostId())) ||
                        (StringUtils.isNotEmpty(boundMoreInfoVO.getPositionName()) && !boundMoreInfoVO.getPositionName().equals(item.getRegularPostName()) )||
                        (StringUtils.isNotEmpty(boundMoreInfoVO.getGradeId()) && !boundMoreInfoVO.getGradeId().equals(item.getRegularGradeId()) )||
                        (StringUtils.isNotEmpty(boundMoreInfoVO.getGradeName()) && !boundMoreInfoVO.getGradeName().equals(item.getRegularGradeName()))){
                    management.setId(item.getId());
                    management.setOrgId(boundMoreInfoVO.getOrganizeId());
                    management.setOrgName(boundMoreInfoVO.getOrganizeName());
                    management.setRegularPostId(boundMoreInfoVO.getPositionId());
                    management.setRegularPostName(boundMoreInfoVO.getPositionName());
                    management.setRegularGradeId(boundMoreInfoVO.getGradeId());
                    management.setRegularGradeName(boundMoreInfoVO.getGradeName());
                    baseMapper.updateById(management);
                }

            }
        });
    }

    private  boolean isSameDay(Date d1, Date d2) {
        LocalDate localDate1 = d1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = d2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return localDate1.equals(localDate2);
    }
    @Override
    public PageListVO<FtbPersonnelsRegularManagementVO> pageForAppList(FtbPersonnelsForAppQueryDTO dto, CultivatePage cultivatePage) {
        Page<FtbPersonnelsRegularManagementVO> page = cultivatePage.coverCultivatePage();
        // 超过转正时间(审批通过,超过实际转正时间,列表不显示)
        //removeTheCorrectionReviewTimeExceeded();
        dto.setUserId(UserProvider.getUser().getUserId());
        if ("1".equals(dto.getFlagByApp())) {
            if ( !UserProvider.getUser().getIsAdministrator() ) {
                // 数据权限userIds
                List<String> userIds = permissionHandling.getUserIdsByUserId(UserProvider.getUser().getUserId());
                if (CollUtil.isNotEmpty(userIds)) {
                    dto.setUserIds(userIds);
                }
            }
        }
        Page<FtbPersonnelsRegularManagementVO> listForApp = baseMapper.getListForApp(page, dto);
        // 查询最新主管
        List<String> userIds = listForApp.getRecords().stream().filter(item -> item.getTransferStatus() == 5).map(FtbPersonnelsRegularManagementVO::getUserId).collect(Collectors.toList());
        supplementalData(userIds, listForApp.getRecords());
        String userId = UserProvider.getUser().getUserId();
        listForApp.getRecords().stream().filter(v->v.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode()) ||
                v.getTransferStatus().equals(FtbPersonnelsAuditTaskEnum.CANCEL.getCode())).forEach(item->{
            if (StringUtils.isNotEmpty(item.getTaskInfoId())) {
                FlowTaskEntity byTaskId = flowTaskApi.findByTaskId(item.getTaskInfoId());
                if (ObjectUtil.isNotEmpty(byTaskId) &&  userId.equals(byTaskId.getCreatorUserId())) {
                    item.setCurrentSponsor(1);
                } else {
                    item.setCurrentSponsor(0);
                }
            }
        });
        return CultivatePage.coverPageList(listForApp);
    }

    /**
     * 补充数据
     * @param userIds
     * @param
     */
    private void supplementalData(List<String> userIds,List<FtbPersonnelsRegularManagementVO> records ) {
        Map<String, UserBoundVO> userMap = new HashMap<>();
        ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getUserPrimaryBoundBatch(userIds, UserProvider.getUser().getTenantId());
        if (actionResult != null && CollUtil.isNotEmpty(actionResult.getData())) {
            userMap = actionResult.getData().stream().collect(Collectors.toMap(UserBoundVO::getId, Function.identity(), (k1, k2)-> k1));
        }
        Map<String, UserBoundVO> finalUserMap = userMap;
        records.forEach(item->{
            String userId = item.getUserId();
            if (finalUserMap.containsKey(userId)){
                UserBoundVO boundMoreInfoVO = finalUserMap.get(userId);
                item.setOrgId(boundMoreInfoVO.getOrganizeId());
                item.setOrgName(boundMoreInfoVO.getOrganizeName());
                item.setRegularPostId(boundMoreInfoVO.getPositionId());
                item.setRegularPostName(boundMoreInfoVO.getPositionName());
                item.setRegularGradeId(boundMoreInfoVO.getGradeId());
                item.setRegularGradeName(boundMoreInfoVO.getGradeName());
                item.setImmediateSuperName(boundMoreInfoVO.getLeaderName());
                item.setImmediateSuperId(boundMoreInfoVO.getLeaderId());
            }
        });
    }

    @Override
    public FtbPersonnelsBubbleCountVO getListCont(String flag) {
        //  flag "1" 我的审批 "2" 抄送
        FtbPersonnelsBubbleCountVO countVO = new FtbPersonnelsBubbleCountVO();
        FtbPersonnelsForAppQueryDTO appQueryDTO = new FtbPersonnelsForAppQueryDTO();
        appQueryDTO.setUserId(UserProvider.getUser().getUserId());
        if ("1".equals(flag)) {
            appQueryDTO.setFlagByApp("2");
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.PENDING.getCode());
            appQueryDTO.setConfigType(FtbPersonnelsCofigEnum.CONVERSION_APPROVAL_CONFIGURATION.getConfigType());
            countVO.setPendingCount(baseMapper.getThePendingApprovalList(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
            countVO.setQuantityUnderCount(baseMapper.getAuditedDataList(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode());
            countVO.setApprovedCount(baseMapper.getAuditedDataList(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode());
            countVO.setApprovalFailedCount(baseMapper.getAuditedDataList(new Page<>(), appQueryDTO).getTotal());
        } else if ("2".equals(flag)) {
            appQueryDTO.setFlagByApp("3");
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
            appQueryDTO.init("3",FtbPersonnelsCofigEnum.CONVERSION_APPROVAL_CONFIGURATION);
            countVO.setQuantityUnderCount(baseMapper.getListForCC(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setStatusList(null);
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode());
            countVO.setApprovedCount(baseMapper.getListForCC(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode());
            countVO.setApprovalFailedCount(baseMapper.getListForCC(new Page<>(), appQueryDTO).getTotal());
        }
        return countVO;
    }

    @Override
    public void clearHistoricalConversionData(List<String> userIds) {
        // 清除所有之前的转正数据
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaQuery();
        wrapper.in(FtbPersonnelsRegularManagement::getUserId,userIds);
        List<FtbPersonnelsRegularManagement> managements = baseMapper.selectList(wrapper);
        // 没有转正数据清除
        if (CollUtil.isEmpty(managements)){
            return;
        }
        // 清除具有审批数据的数据
        managements.stream().filter(vo-> StringUtils.isNotEmpty(vo.getTaskInfoId()))
                .forEach (item->runTaskService.deleteReviewProcessAndRecords(item.getTaskInfoId(),item.getId()));
        // 清楚转正数据
        List<String> collect = managements.stream().map(FtbPersonnelsRegularManagement::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<FtbPersonnelsRegularManagement> lambdaed = Wrappers.lambdaUpdate();
        lambdaed.in(FtbPersonnelsRegularManagement::getId, collect);
        baseMapper.delete(lambdaed);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public String applyForRegularization(FtbPersonnelsRegularCreateDTO createDto) {
        // 校验是否是重复办理转正
        String taskId = createDto.getTaskId();
        String id = createDto.getId();
        checkWhetherItIsRepeated(id, taskId);
        String resultStr = "";
        // 校验转正是否完成
        verifyWhetherTheUserHasCompletedTheProcess(createDto.getUserId());
        // 校验是否处于流程中
        checkWhetherTheCheckIsInTheProcess(createDto.getUserId());
        FtbPersonnelsRegularManagement regularManagement = FtbPersonnelsRegularCreateDTO.coverFtbPersonnelsRegularManagement(createDto);
        if (StringUtils.isNotEmpty(regularManagement.getId())) {
            // 删除上传的文件重新上传
            LambdaUpdateWrapper<FtbCultivateFile> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(FtbCultivateFile::getBusinessId, regularManagement.getId());
            ftbCultivateFileService.remove(updateWrapper);
        }
        String onboardPostId = regularManagement.getOnboardPostId();
        if (StringUtils.isNotEmpty(onboardPostId)) {
            ActionResult<PositionVO> voActionResult = v2PositionApi.infoPosition(onboardPostId);
            if (ObjectUtil.isNotEmpty(voActionResult) && ObjectUtil.isNotEmpty(voActionResult.getData()))regularManagement.setOnboardPostName(voActionResult.getData().getFullName());
        }
        String onboardGradeId = regularManagement.getOnboardGradeId();
        if (StringUtils.isNotEmpty(onboardGradeId)) {
            ActionResult<GradeVO> gradeVOActionResult = v2GradesApi.infoGrade(onboardPostId);
            if (ObjectUtil.isNotEmpty(gradeVOActionResult) && ObjectUtil.isNotEmpty(gradeVOActionResult.getData()))regularManagement.setOnboardPostName(gradeVOActionResult.getData().getFullName());
        }
        FtbPersonnelsResult result =
                FtbPersonnelsResult.getResult(createDto.getSource(), createDto.getFlag());
        String userId = UserProvider.getUser().getUserId();
        // 如果员工自己申请需要清除未办理数据
        if (createDto.getUserId().equals(userId) && result.source == 0){
            LambdaQueryWrapper<FtbPersonnelsRegularManagement> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(FtbPersonnelsRegularManagement::getUserId,createDto.getUserId());
            lambdaQuery.eq(FtbPersonnelsRegularManagement::getTransferStatus,FtbPersonnelsAuditTaskEnum.NOT_PROCESSED.getCode());
            FtbPersonnelsRegularManagement management = baseMapper.selectOne(lambdaQuery);
            if (ObjectUtil.isNotEmpty(management)){
                baseMapper.deleteById(management.getId());
            }
        }
        regularManagement.setTransferStatus(result.state);
        regularManagement.setApplicationSource(result.source);
        regularManagement.setCreatorTime(new Date());
        regularManagement.setTaskInfoId(null);
        // 重新设置为有效
        regularManagement.setEnableMark(0L);
        regularManagement.setVersionNum(1);
        // 添加薪资详情
        List<FtbPersonnelsSalaryInfo> salaryStructureList = createDto.getSalaryStructureList();
        // 校验岗位是否还存在
        QueryUserBoundDTO checkExistByPositionDTO = new QueryUserBoundDTO();
        checkExistByPositionDTO.setPositionId(createDto.getRegularPostId());
        checkExistByPositionDTO.setGradeId(createDto.getRegularGradeId());
        doCheckOrgPositionGradesBoundDTO(checkExistByPositionDTO);
        //  薪酬冲突
        // 没有值时进行校验薪酬时间冲突问题
        Integer isDelete = createDto.getIsDelete();
        if ("1".equals(createDto.getIsAdjustSalary()) && isDelete == null){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            createDto.setPayrollEffectiveDate(createDto.getActualConverDate());
            String format = simpleDateFormat.format(createDto.getPayrollEffectiveDate());
            ActionResult<List<UserSalaryHistoryVo>> historyByChangeDate = querySalaryApi.getHistoryByChangeDate(format, createDto.getUserId());
            if (historyByChangeDate == null){
                throw new RuntimeException("获取薪酬数据失败!");
            }
            List<UserSalaryHistoryVo> data = historyByChangeDate.getData();
            if (CollUtil.isNotEmpty(data)) return "5";
        }
        if ("1".equals(createDto.getIsAdjustSalary() ) && CollUtil.isNotEmpty(salaryStructureList)) {
            regularManagement.setSalaryStructureList(JSONObject.toJSONString(salaryStructureList));
        }
        // 办理审批人更新
        regularManagement.setCreatorUserId(UserProvider.getUser().getUserId());
        this.saveOrUpdate(regularManagement);
        String managementId = regularManagement.getId();
        // 转正前调用花名册进行员工状态同步
        staffRosterService.recordPreRegularStatus(regularManagement.getUserId());
        // 创建审批
        if (result.source != 2 && result.source != 3) {
            String runTaskId = runTaskService.startTheReviewProcess(managementId,
                    FtbPersonnelsCofigEnum.CONVERSION_APPROVAL_CONFIGURATION.getConfigType(),
                    createDto.getOrgId(),
                    regularManagement.getUserId());
            // 同步id
            LambdaUpdateWrapper<FtbPersonnelsRegularManagement> lambdaUpdate = Wrappers.lambdaUpdate();
            lambdaUpdate.set(FtbPersonnelsRegularManagement::getTaskInfoId, runTaskId);
            lambdaUpdate.eq(FtbPersonnelsRegularManagement::getId,managementId);
            baseMapper.update(null,lambdaUpdate);
        }else if (result.source == 2){
            UserInfo userInfo = UserProvider.getUser();
            if (regularManagement.getUserId().equals(userInfo.getUserId())){
                throw new RuntimeException("无法给自己进行手动转正!");
            }
            // 转正通知
            // 转正员工同步
            messageNotifications(regularManagement.getUserId(),true);
            // 手动调整薪酬
            if ("1".equals(regularManagement.getIsAdjustSalary()) && CollUtil.isNotEmpty(salaryStructureList) ){
                synchronizePayrollData(regularManagement);
            }
            // 实际转正时间选择当前时间之前的直接手动变更数据
            changeEmployeeData(regularManagement);
        }
        //通过文件事件监听信息
        SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(FileEventDTO.builder()
                .files(createDto.getFiles())
                .businessTypeID(managementId)
                .type(FileEventDTO.FileType.REGULAR_MANAGEMENT)
                .build()));

        return resultStr;
    }

    /**
     * 实际转正时间选择当前时间之前的直接手动变更数据
     *
     * @param regularManagement
     */
    public void changeEmployeeData(FtbPersonnelsRegularManagement regularManagement){
        if ( regularManagement.getActualConverDate() == null || !DateUtil.date().isAfter(regularManagement.getActualConverDate()) )return;
        syncRegularStatus(UserProvider.getUser().getTenantId());
    }

    private void checkWhetherItIsRepeated(String id, String taskId) {
        if (StringUtils.isNotEmpty(id) || StringUtils.isNotEmpty(taskId)){
            LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq( StringUtils.isNotEmpty(id),SuperBaseEntity.SuperIBaseEntity::getId, id);
            queryWrapper.eq(StringUtils.isNotEmpty(taskId),FtbPersonnelsRegularManagement::getTaskInfoId, taskId);
            queryWrapper.in(FtbPersonnelsRegularManagement::getTransferStatus,List.of(FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode(),
                    FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode()));
            Long aLong = baseMapper.selectCount(queryWrapper);
            if (aLong > 0){
                throw new RuntimeException("该用户已办理转正,无需重复办理!");
            }
        }
    }

    @GlobalTransactional
    @Override
    public ActionResult<Void> applyForRegularizationForOA(FtbPersonnelsRegularCreateDTO createDto) {

        // 校验是否处于流程中
        ActionResult<Void> actionResult = new ActionResult<>();
        actionResult.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        actionResult.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        checkWhetherTheCheckIsInTheProcess(createDto.getUserId());
        boolean after = createDto.getDateOfEntry().after(createDto.getActualConverDate());
        if (after) throw new RuntimeException("转正日期不能小于入职日期!");
        List<FtbCultivateOfflineFileDTO> fileDTOS = new ArrayList<>();
        if (StringUtils.isNotEmpty(createDto.getFilesWithOa())){
            String filesWithOa = createDto.getFilesWithOa();
            fileDTOS = JSONObject.parseArray(filesWithOa, FtbCultivateOfflineFileDTO.class);
        }
        FtbPersonnelsRegularManagement regularManagement = FtbPersonnelsRegularCreateDTO.coverFtbPersonnelsRegularManagement(createDto);
        // 校验转正是否完成
        verifyWhetherTheUserHasCompletedTheProcess(regularManagement.getUserId());
        if(createDto.getSource() == 1 &&  regularManagement.getUserId().equals(UserProvider.getUser().getUserId())) {
            throw new DataException("不能为自己办理!");
        }
        checkWhetherItIsRepeated(regularManagement.getId(), null);
        StaffHomeDto staffHomeDto = staffRosterService.queryWorkerHomeDetail(regularManagement.getUserId());
        //①工作状态为试用②工作状态为试岗且有试用期
        boolean workStatusForSg = "306".equals(staffHomeDto.getWorkerStatus()) && !"100".equals(staffHomeDto.getProbationPeriod());
        if (!("302".equals(staffHomeDto.getWorkerStatus()) || workStatusForSg)){
            actionResult.setMsg("该员工无试用期,不需要发起转正!");
            actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return actionResult;
        }
        if(staffHomeDto.getActualStartDate().after(regularManagement.getActualConverDate()) ||
                staffHomeDto.getActualStartDate().compareTo(regularManagement.getActualConverDate()) == 0){
            actionResult.setMsg("转正日期不能早于或者等于入职日期!");
            actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return actionResult;
        }

        FtbPersonnelsResult result = FtbPersonnelsResult.getResult(createDto.getSource(), createDto.getFlag());
        regularManagement.setTransferStatus(result.state);
        regularManagement.setApplicationSource(result.source);
        if (result.source != 0){
            Date payrollEffectiveDate = regularManagement.getPayrollEffectiveDate();
            payrollEffectiveDate = DateUtil.endOfDay(payrollEffectiveDate);
            List<FtbPersonnelsSecondmentManagement> serviceIdList = ftbPersonnelsSecondmentManagementService.salarySecondmentCrossover(regularManagement.getUserId(),
                    payrollEffectiveDate);
            if(CollUtil.isNotEmpty(serviceIdList)){
                String collected = serviceIdList.stream().map(v -> {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    return sdf.format(v.getSecondmentStartTime()) + "~" + sdf.format(v.getSecondmentEndTime());
                }).collect(Collectors.joining(","));
                String joined = String.format("当前办理转正选择日期为%s生效，\n" +
                                "检测到您有一项借调业务的起止时间(%s)与当前办理业务的生效日期\n" +
                                "重叠，请重新选择日期(可选择借调开始之前的日期或者借调结束之后的日期)",
                        DateUtil.format(regularManagement.getPayrollEffectiveDate(),"yyyy-MM-dd"),collected);
                throw new RuntimeException(joined);
            }
        }
        if (result.source != 0 && !UserProvider.getUser().getIsAdministrator()) {
            // 权限用户
            List<String> userIds = permissionsUtils.obtainPersonnelUserIdDataPermissions(UserProvider.getUser().getUserId(), PermissionsEnums.PERSONNEL_MANAGEMENT_WEB.getValue(), "Web");
            // 当前人不是本人申请,且权限中有当前可以办理人
            if ((regularManagement.getApplicationSource() != 0) && (CollUtil.isNotEmpty(userIds) && !userIds.contains(regularManagement.getUserId()))) {
                actionResult.setMsg("当前人办理人不具有该员工办理权限!");
                actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                return actionResult;
            }
        }
        if (ObjectUtil.isNotEmpty(staffHomeDto)){
            buildYourData(regularManagement,staffHomeDto);
        }
        if (StringUtils.isNotEmpty(regularManagement.getId())) {
            // 删除上传的文件重新上传
            LambdaUpdateWrapper<FtbCultivateFile> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(FtbCultivateFile::getBusinessId, regularManagement.getId());
            ftbCultivateFileService.remove(updateWrapper);
        }
        String onboardPostId = regularManagement.getOnboardPostId();
        if (StringUtils.isNotEmpty(onboardPostId)) {
            ActionResult<PositionVO> voActionResult = v2PositionApi.infoPosition(onboardPostId);
            if (ObjectUtil.isNotEmpty(voActionResult)  && voActionResult.getData() != null )regularManagement.setOnboardPostName(voActionResult.getData().getFullName());
        }
        String onboardGradeId = regularManagement.getOnboardGradeId();
        if (StringUtils.isNotEmpty(onboardGradeId)) {
            ActionResult<GradeVO> gradeVOActionResult = v2GradesApi.infoGrade(onboardPostId);
            if (ObjectUtil.isNotEmpty(gradeVOActionResult) && gradeVOActionResult.getData() != null)regularManagement.setOnboardPostName(gradeVOActionResult.getData().getFullName());
        }
        String userId = UserProvider.getUser().getUserId();
        // 如果员工自己申请需要清除未办理数据
        if (regularManagement.getUserId().equals(userId) && result.source == 0){
            LambdaQueryWrapper<FtbPersonnelsRegularManagement> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(FtbPersonnelsRegularManagement::getUserId,regularManagement.getUserId());
            lambdaQuery.eq(FtbPersonnelsRegularManagement::getTransferStatus,FtbPersonnelsAuditTaskEnum.NOT_PROCESSED.getCode());
            FtbPersonnelsRegularManagement management = baseMapper.selectOne(lambdaQuery);
            if (ObjectUtil.isNotEmpty(management)){
                baseMapper.deleteById(management.getId());
            }
            regularManagement.setLastModifyUserId(UserProvider.getUser().getUserId());
            regularManagement.setLastModifyTime(new Date());
        }
        regularManagement.setCreatorTime(new Date());
        // 重新设置为有效
        regularManagement.setEnableMark(0L);
        regularManagement.setVersionNum(1);
        // 第二办理没有填写转正备注将数据进行清除
        if (regularManagement.getId() != null ){
            FtbPersonnelsRegularManagement management = baseMapper.selectById(regularManagement.getId());
            if (management != null && StringUtils.isNotEmpty(management.getRemarksConver())){
                LambdaUpdateWrapper<FtbPersonnelsRegularManagement> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId,regularManagement.getId());
                updateWrapper.set(FtbPersonnelsRegularManagement::getRemarksConver,null);
                baseMapper.update(null,updateWrapper);
            }
        }
        // 添加薪资详情
        List<FtbPersonnelsSalaryInfo> salaryStructureList = createDto.getSalaryStructureList();
        if (CollUtil.isEmpty(salaryStructureList)  && "1".equals(createDto.getIsAdjustSalary()) ){
            actionResult.setMsg("目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
            actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return actionResult;
        }else if (CollUtil.isNotEmpty(salaryStructureList) && "1".equals(createDto.getIsAdjustSalary())){
            regularManagement.setSalaryStructureList(JSONObject.toJSONString(salaryStructureList));
        }
        UserInfo userInfo = UserProvider.getUser();
        if (result.source == 2  && regularManagement.getUserId().equals(userInfo.getUserId())){
            actionResult.setMsg("无法给自己进行手动转正!");
            actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return actionResult;
        }
        // 清除之前的数据
        if (StringUtils.isNotEmpty(regularManagement.getUserId())){
            LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPersonnelsRegularManagement::getEnableMark,0);
            queryWrapper.eq(FtbPersonnelsRegularManagement::getUserId,regularManagement.getUserId());
            List<FtbPersonnelsRegularManagement> management = baseMapper.selectList(queryWrapper);
            if (CollUtil.isNotEmpty(management)){
                // 清除未办理数据
                management.forEach(v->baseMapper.deleteById(v.getId()));
            }
        }
        regularManagement.setCreatorUserId(UserProvider.getUser().getUserId());
        this.saveOrUpdate(regularManagement);
        String managementId = regularManagement.getId();
        // 转正前调用花名册进行员工状态同步
        staffRosterService.recordPreRegularStatus(regularManagement.getUserId());
        // 创建审批
        if (result.source == 0 || result.source == 1) {
            // 同步id
            LambdaUpdateWrapper<FtbPersonnelsRegularManagement> lambdaUpdate = Wrappers.lambdaUpdate();
            lambdaUpdate.set(FtbPersonnelsRegularManagement::getTaskInfoId, createDto.getTaskId());
            lambdaUpdate.eq(FtbPersonnelsRegularManagement::getId,managementId);
            baseMapper.update(null,lambdaUpdate);
        }
        //通过文件事件监听信息
        SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(FileEventDTO.builder()
                .files(fileDTOS)
                .businessTypeID(managementId)
                .type(FileEventDTO.FileType.REGULAR_MANAGEMENT)
                .build()));
        return actionResult;
    }

    /**
     * 构建数据
     * @param regularManagement
     * @param staffHomeDto
     */
    private void buildYourData(FtbPersonnelsRegularManagement regularManagement, StaffHomeDto staffHomeDto) {
        regularManagement.setSystemWokerId(staffHomeDto.getSystemWokerId());
        regularManagement.setPhoneNumber(staffHomeDto.getPhone());
        regularManagement.setUserName(staffHomeDto.getName());
        regularManagement.setDateOfEntry(staffHomeDto.getActualStartDate());
        regularManagement.setJobNumber(staffHomeDto.getWorkerNo());
        regularManagement.setProbation(staffHomeDto.getProbationPeriod());
        regularManagement.setProbationPeriodDay(staffHomeDto.getProbationPeriodDay());
        regularManagement.setImmediateSuperId(staffHomeDto.getReportsTo());
        regularManagement.setImmediateSuperName(staffHomeDto.getReportsToName());
        regularManagement.setSchedConverDate(staffHomeDto.getPlanProbationaryDate());
        regularManagement.setStartingSalary(staffHomeDto.getEntrySalary());
        regularManagement.setOnboardPostId(staffHomeDto.getCurrPosition());
        regularManagement.setOnboardPostName(staffHomeDto.getCurrPositionName());
        regularManagement.setOnboardGradeId(staffHomeDto.getCurrRank());
        regularManagement.setOnboardGradeName(staffHomeDto.getCurrRankName());
        OrganizeEntity organizeEntity = personnelOrgUtils.queryOrganizeInfo(regularManagement.getOrgId());
        if (ObjectUtil.isNotEmpty(organizeEntity))regularManagement.setOrgName(organizeEntity.getFullName());
        PositionEntity positionEntity = personnelOrgUtils.queryPosition(regularManagement.getRegularPostId());
        if (ObjectUtil.isNotEmpty(positionEntity)) regularManagement.setRegularPostName(positionEntity.getFullName());
        PositionGradesInfoVO gradesInfoVO = personnelOrgUtils.queryRank(regularManagement.getRegularGradeId());
        if (ObjectUtil.isNotEmpty(gradesInfoVO))regularManagement.setRegularGradeName(gradesInfoVO.getFullName());
    }

    @GlobalTransactional
    @Override
    public  ActionResult<Void> regularizationApprovalForOA(FtbPersonnelsSalaryAuditDto auditDto) {
        ActionResult<Void> actionResult = new ActionResult<>();
        actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        actionResult.setMsg( FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPersonnelsRegularManagement::getTaskInfoId,auditDto.getTaskId());
        FtbPersonnelsRegularManagement regularManagement = baseMapper.selectOne(queryWrapper);
        // 选择通过需要校验组织是否存在
        if ("1".equals(auditDto.getFlag()))verify(regularManagement);
        //FtbPersonnelsAuditTaskEnum performReview = runTaskService.performReview(auditDto);
        // 根据oa返回进行状态更新
        FtbPersonnelsAuditTaskEnum performReview = auditDto.getFlag().equals("0") ? FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED : FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED;
        LambdaUpdateWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(FtbPersonnelsRegularManagement::getId, regularManagement.getId());
        wrapper.set(FtbPersonnelsRegularManagement::getTransferStatus, performReview.getCode());
        if (StringUtils.isNotEmpty(auditDto.getIsAdjustSalary())){
            wrapper.set(FtbPersonnelsRegularManagement::getIsAdjustSalary,auditDto.getIsAdjustSalary());
        }
        if (StringUtils.isNotEmpty(auditDto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructure,auditDto.getSalaryStructure());
        }
        if ( ObjectUtil.isNotEmpty(auditDto.getSalary())){
            wrapper.set(FtbPersonnelsRegularManagement::getRegularSalary,auditDto.getSalary());
        }
        if (ObjectUtil.isNotEmpty(auditDto.getPayrollEffectiveDate())){
            wrapper.set(FtbPersonnelsRegularManagement::getPayrollEffectiveDate,auditDto.getPayrollEffectiveDate());
        }
        if (StringUtils.isNotEmpty(auditDto.getReasonsForSalaryAdjustments())) {
            wrapper.set(FtbPersonnelsRegularManagement::getReasonsForSalaryAdjustments, auditDto.getReasonsForSalaryAdjustments());
        }
        if (StringUtils.isNotEmpty(auditDto.getPayrollSequenceId())){
            wrapper.set(FtbPersonnelsRegularManagement::getPayrollSequenceId, auditDto.getPayrollSequenceId());
        }
        if (StringUtils.isNotEmpty(auditDto.getPayrollSequenceName())){
            wrapper.set(FtbPersonnelsRegularManagement::getPayrollSequenceName, auditDto.getPayrollSequenceName());
        }
        if (ObjectUtil.isNotEmpty(auditDto.getPayrollSequence())){
            wrapper.set(FtbPersonnelsRegularManagement::getPayrollSequence, auditDto.getPayrollSequence());
        }
        List<FtbPersonnelsSalaryInfo> salaryStructureList = auditDto.getSalaryStructureList();
        if(CollUtil.isNotEmpty(salaryStructureList)){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructureList,
                    JSONObject.toJSONString(salaryStructureList));
        }
        // 薪资员工自己申请的
        if(ObjectUtil.isNotEmpty(auditDto.getIsAdjustSalary())){
            if (CollUtil.isEmpty(salaryStructureList)  && "1".equals(auditDto.getIsAdjustSalary()) ){
                actionResult.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                actionResult.setMsg( "目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
                return actionResult;
            }
            wrapper.set(FtbPersonnelsRegularManagement::getIsAdjustSalary,auditDto.getIsAdjustSalary());
        }
        if(ObjectUtil.isNotEmpty(auditDto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryStructure,auditDto.getSalaryStructure());
        }
        baseMapper.update(null, wrapper);
        if (FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.equals(performReview)) {
            // 成功通知
            FtbPersonnelsRegularManagement thisRegularInfo = baseMapper.selectById(regularManagement.getId());
            if (thisRegularInfo.getApplicationSource() == 0){
                Date payrollEffectiveDate = thisRegularInfo.getPayrollEffectiveDate();
                payrollEffectiveDate = DateUtil.endOfDay(payrollEffectiveDate);
                List<FtbPersonnelsSecondmentManagement> serviceIdList = ftbPersonnelsSecondmentManagementService.salarySecondmentCrossover(thisRegularInfo.getUserId(),
                        payrollEffectiveDate);
                if(CollUtil.isNotEmpty(serviceIdList)){
                    String collected = serviceIdList.stream().map(v -> {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        return sdf.format(v.getSecondmentStartTime()) + "~" + sdf.format(v.getSecondmentEndTime());
                    }).collect(Collectors.joining(","));
                    String joined = String.format("当前办理转正选择日期为%s生效，\n" +
                                    "检测到您有一项借调业务的起止时间(%s)与当前办理业务的生效日期\n" +
                                    "重叠，请重新选择日期(可选择借调开始之前的日期或者借调结束之后的日期)",
                                DateUtil.format(payrollEffectiveDate,"yyyy-MM-dd"),collected);
                    throw new RuntimeException(joined);
                }
            }
            messageNotifications(regularManagement.getUserId(), true);
            synchronizePayrollData(thisRegularInfo);
            changeEmployeeData(regularManagement);
        }else {
            // 失败通知
            messageNotifications(regularManagement.getUserId(), false);
        }
        return actionResult;
    }

    public  void verifyWhetherTheUserHasCompletedTheProcess(String userId){
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbPersonnelsRegularManagement::getTransferStatus,
                List.of( FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode(), FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode()));
        queryWrapper.eq(FtbPersonnelsRegularManagement::getEnableMark, 0);
        queryWrapper.eq(FtbPersonnelsRegularManagement::getUserId, userId);
        Long aLong = baseMapper.selectCount(queryWrapper);
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = Wrappers.lambdaQuery();
        wrapper.in(FtbPersonnelsStaffRoster::getWorkerStatus,"303");
        wrapper.eq(FtbPersonnelsStaffRoster::getUserId,userId);
        long rostCount = staffRosterService.count(wrapper);
        if(aLong > 0  && rostCount > 0) throw new RuntimeException("当前人员已经完成了转正请勿重复办理!");
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper2 = Wrappers.lambdaQuery();
        wrapper2.notIn(FtbPersonnelsStaffRoster::getWorkerStatus,"304","305","303");
        wrapper2.eq(FtbPersonnelsStaffRoster::getUserId,userId);
        long rostCount2 = staffRosterService.count(wrapper2);
        if(aLong > 0 && rostCount2 > 0) throw new RuntimeException("当前人员已经办理转正,还未到实际转正时间,请勿重复办理!");
    }
    @Override
    public void syncRegularStatus(String tenantId) {
        LambdaQueryWrapper<FtbPersonnelsRegularManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbPersonnelsRegularManagement::getTransferStatus,
                List.of( FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode(), FtbPersonnelsAuditTaskEnum.MANUAL_CONTROL.getCode()));
        queryWrapper.eq(FtbPersonnelsRegularManagement::getEnableMark, 0);
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = Wrappers.lambdaQuery();
        wrapper.in(FtbPersonnelsStaffRoster::getWorkerStatus,"302");
        List<FtbPersonnelsStaffRoster> list = staffRosterService.list(wrapper);
        List<String> userIds = list.stream().map(FtbPersonnelsStaffRoster::getUserId).collect(Collectors.toList());
        if(CollUtil.isEmpty(userIds)) return;
        queryWrapper.in(FtbPersonnelsRegularManagement::getUserId, userIds);
        List<FtbPersonnelsRegularManagement> managements = baseMapper.selectList(queryWrapper);
        Date date = new Date();
        try {
            managements.stream().filter(v->{
                Date actualConverDate = v.getActualConverDate();
                if (date.after(actualConverDate)) return true;
                return false;
            }).forEach(regularManagement->{
                StaffRegularDto regularDto = StaffRegularDto.coverFtbPersonnelsRegularManagement(regularManagement);
                staffRosterService.innerChangeRegular(regularManagement.getUserId(), regularDto, regularManagement.getRegularSalary(),tenantId);
            });

        }catch (Exception e){
            e.printStackTrace();
            log.error("执行员工转正变更状态失败!");
        }

    }

    @Override
    public void applyForRegularizationBatch(List<FtbPersonnelsRegularCreateDTO> createDTO) {
        long start = System.currentTimeMillis();
        List<FtbPersonnelsRegularManagement> ftbPersonnelsRegularManagements = createDTO.stream().map(createDto -> {
            FtbPersonnelsRegularManagement regularManagement = FtbPersonnelsRegularCreateDTO.coverFtbPersonnelsRegularManagement(createDto);
            FtbPersonnelsResult result =
                    FtbPersonnelsResult.getResult(createDto.getSource(), createDto.getFlag());
            regularManagement.setTransferStatus(result.state);
            regularManagement.setApplicationSource(result.source);
            regularManagement.setCreatorTime(new Date());
            regularManagement.setTaskInfoId(null);
            // 重新设置为有效
            regularManagement.setEnableMark(0L);
            regularManagement.setVersionNum(1);
            return regularManagement;
        }).collect(Collectors.toList());
        // 转正通知
        this.saveBatch(ftbPersonnelsRegularManagements);
        long end = System.currentTimeMillis();
        log.error(String.format("花名册导入批量转正(applyForRegularizationBatch) 记录数:%d 耗时：%dms",
                ftbPersonnelsRegularManagements.size(), (end - start)));
    }

    private void synchronizePayrollData(FtbPersonnelsRegularManagement thisRegularInfo,String... tenantIds) {
        String dataSalaryStructureList = thisRegularInfo.getSalaryStructureList();
        if ("1".equals(thisRegularInfo.getIsAdjustSalary()) && StringUtils.isNotEmpty(dataSalaryStructureList) &&
                !("null".equals(dataSalaryStructureList) || "[]".equals(dataSalaryStructureList))){
            List<FtbPersonnelsSalaryInfo> salaryInfos = JSONObject.parseArray(dataSalaryStructureList, FtbPersonnelsSalaryInfo.class);
            UserInfoWithSalary userInfoWithSalary = getUserInfoWithSalary(thisRegularInfo);
            String creatorUserId = thisRegularInfo.getCreatorUserId();
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPersonnelsStaffRoster::getUserId, creatorUserId);
            FtbPersonnelsStaffRoster serviceOne = staffRosterService.getOne(queryWrapper);
            if (Objects.nonNull(serviceOne)){
                userInfoWithSalary.setOperatorWorkNo(serviceOne.getSystemWokerId());
            }
            userInfoWithSalary.setTaskId(thisRegularInfo.getTaskInfoId());
            // 入职时间
            userInfoWithSalary.setEntryDate(thisRegularInfo.getDateOfEntry());
            // 计划转正时间
            userInfoWithSalary.setBeComeDate(thisRegularInfo.getActualConverDate());
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.eq(FtbPersonnelsStaffRoster::getUserId, thisRegularInfo.getUserId());
            FtbPersonnelsStaffRoster staffRoster = staffRosterService.getOne(queryWrapper2);
            if (Objects.nonNull(staffRoster)){
                userInfoWithSalary.setUserTypeId(staffRoster.getWorkerType());
            }
            String recordId = salaryService.saveTheChangePayInformation(salaryInfos,
                    thisRegularInfo.getUserId(),
                    thisRegularInfo.getPayrollEffectiveDate(),
                    userInfoWithSalary,
                    "1",
                    thisRegularInfo.getReasonsForSalaryAdjustments(),
                    "1",
                    0,
                    thisRegularInfo.getSalaryType(),
                    thisRegularInfo.getPayrollSequenceId(),
                    tenantIds.length > 0 ? tenantIds[0] : null);
            LambdaUpdateWrapper<FtbPersonnelsRegularManagement> wrapper = Wrappers.lambdaUpdate();
            wrapper.set(FtbPersonnelsRegularManagement::getSalaryRecordId, recordId);
            wrapper.eq(FtbPersonnelsRegularManagement::getId, thisRegularInfo.getId());
            baseMapper.update(null, wrapper);
        }
    }

    @NotNull
    private static UserInfoWithSalary getUserInfoWithSalary(FtbPersonnelsRegularManagement regularManagement) {
        UserInfoWithSalary userInfoWithSalary = new UserInfoWithSalary();
        userInfoWithSalary.setRankName(regularManagement.getRegularGradeName());
        userInfoWithSalary.setRankId(regularManagement.getRegularGradeId());
        userInfoWithSalary.setFOrgId(regularManagement.getOrgId());
        userInfoWithSalary.setFOrgName(regularManagement.getOrgName());
        userInfoWithSalary.setPostId(regularManagement.getRegularPostId());
        userInfoWithSalary.setPostName(regularManagement.getRegularPostName());
        return userInfoWithSalary;
    }


    private void checkWhetherTheCheckIsInTheProcess(String userId) {
        // null 不处于 ,1 转正 2,调岗, 3离职
        String s = runTaskService.checkWhetherTheCurrentPersonnelIsInTheReviewProcess(userId);
        if (StringUtil.isNotEmpty(s)){
            // 1 转正 2 调岗, 3 离职
            String str="";
            if (StringUtil.isNotEmpty(s)) {
                // 1 转正 2 调岗, 3 离职
                switch (s) {
                    case "1":
                        str = "转正";
                        break;
                    case "2":
                        str = "调岗";
                        break;
                    case "3":
                        str = "离职";
                        break;
                    case "4":
                        str = "晋升";
                        break;
                    case "5":
                        str = "调店";
                        break;
                    case "6":
                        str = "降职";
                        break;
                    case "7":
                        str = "借调";
                        break;
                }
            }
            throw new RuntimeException("当前人员处于"+str+"审批中,请勿重复进行审批!");
        }
    }

    @Override
    public FtbPersonnelsRegularInfoVO checkTheDetailsOfRegularizationApproval(String id) {
        FtbPersonnelsRegularManagement regularManagement = baseMapper.selectById(id);
        if (regularManagement == null) {return null;}
        FtbPersonnelsRegularInfoVO regularInfoVO = FtbPersonnelsRegularManagement.coverFtbPersonnelsRegularInfoVO(regularManagement);
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsStaffRoster::getUserId,regularInfoVO.getUserId());
        FtbPersonnelsStaffRoster one = staffRosterService.getOne(wrapper);
        if (Objects.equals(regularInfoVO.getTransferStatus(), FtbPersonnelsAuditTaskEnum.NOT_PROCESSED.getCode())){
            ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getUserPrimaryBoundBatch(List.of(regularInfoVO.getUserId()), null);
            if (actionResult != null &&  CollUtil.isNotEmpty(actionResult.getData())) {
                List<UserBoundVO> workerGroupDataDtos = actionResult.getData();
                UserBoundVO boundMoreInfoVO = workerGroupDataDtos.get(0);
                regularInfoVO.setOrgId(boundMoreInfoVO.getOrganizeId());
                regularInfoVO.setOrgName(boundMoreInfoVO.getOrganizeName());
                regularInfoVO.setRegularPostId(boundMoreInfoVO.getPositionId());
                regularInfoVO.setRegularPostName(boundMoreInfoVO.getPositionName());
                regularInfoVO.setRegularGradeId(boundMoreInfoVO.getGradeId());
                regularInfoVO.setRegularGradeName(boundMoreInfoVO.getGradeName());
                regularInfoVO.setTeamID(boundMoreInfoVO.getStoreTeamId());
                regularInfoVO.setTeamName(boundMoreInfoVO.getStoreTeamName());
                regularInfoVO.setImmediateSuperId(boundMoreInfoVO.getLeaderId());
                regularInfoVO.setImmediateSuperName(boundMoreInfoVO.getLeaderName());
            }
        }
        regularInfoVO.setUserName(one.getName());
        ActionResult<List<UserBoundVO>> allUserInfoBatch = v2UserApi.getAllUserInfoBatch(List.of(regularManagement.getCreatorUserId()), null);
        if (ObjectUtil.isNotEmpty(allUserInfoBatch) && CollUtil.isNotEmpty(allUserInfoBatch.getData())){
            regularInfoVO.setCreatorUserName(allUserInfoBatch.getData().get(0).getName());
        }
        FtbPersonnelsAuditInfoVO auditInfoVO = subConfigService.queryAuditSubConfig(regularInfoVO.getOrgId(), FtbPersonnelsCofigEnum.CONVERSION_APPROVAL_CONFIGURATION);
        regularInfoVO.setAuditInfo(auditInfoVO);
        // 查询当前申请时上传的文件信息
        List<FtbCultivateFile> list = ftbCultivateFileService.lambdaQuery().eq(FtbCultivateFile::getBusinessId, id)
                .eq(FtbCultivateFile::getType,FileEventDTO.FileType.REGULAR_MANAGEMENT.getType()).list();
        List<FtbCultivateOfflineFileVO> fileVOS = list.stream()
                .map(FtbCultivateOfflineFileVO::convertFtbCultivateOfflineFileVO).collect(Collectors.toList());
        regularInfoVO.setFiles(fileVOS);
        //查询框考勤组信息
        List<AttendanceUserGroupVo> attendanceUserGroup = attendanceGroupApi.getAttendanceUserGroup(List.of(regularManagement.getUserId()));
        if (CollectionUtil.isNotEmpty(attendanceUserGroup)) {
            List<String> groupName = new ArrayList<>();
            //stram获取考勤组名称
            for (AttendanceUserGroupVo attendanceUserGroupVo : attendanceUserGroup) {
                groupName.add(attendanceUserGroupVo.getGroupName());
            }
            regularInfoVO.setAttendanceGroupName(String.join(", ", groupName));
        }
        return regularInfoVO;
    }

    /**
     * 所属组织-岗位-职等校验
     */
    public void doCheckOrgPositionGradesBoundDTO(QueryUserBoundDTO dto) {
        String positionId = dto.getPositionId();
        ActionResult<PositionVO> voActionResult = v2PositionApi.infoPosition(dto.getPositionId());
        if ( Objects.isNull(voActionResult) || voActionResult.getCode() != 200 ) {
            throw new RuntimeException("目标岗位不存在，无法继续提交!");
        }
        if (StringUtils.isEmpty(dto.getGradeId()))  return;
        QueryGradeListDTO listDTO = new QueryGradeListDTO();
        listDTO.setPositionId(positionId);
        ActionResult<List<GradeVO>> listGrades = v2GradesApi.listGrades(listDTO);
        if (listGrades.getCode() == 200 && CollUtil.isNotEmpty(listGrades.getData())) {
            if (listGrades.getData().stream().noneMatch(v -> v.getId().equals(dto.getGradeId()))) {
                throw new RuntimeException("目标职级不存在，无法继续提交!");
            }
        }
    }
}
