package jnpf.personnels.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
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.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import io.seata.spring.annotation.GlobalTransactional;
import jnpf.attendance.AttendanceGroupApi;
import jnpf.attendance.AttendanceUserApi;
import jnpf.attendance.dto.GroupUpdateByUserDTO;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.base.vo.PageListVO;
import jnpf.cultivate.mapper.FtbCultivatePositionIdentifyResultMapper;
import jnpf.cultivate.mapper.FtbCultivatePromotionMemberMapper;
import jnpf.cultivate.mapper.FtbCultivatePromotionNewMapper;
import jnpf.cultivate.service.CultivateIdentifyApplyService;
import jnpf.cultivate.service.FtbCultivateCourseService;
import jnpf.cultivate.service.FtbCultivateExamUserService;
import jnpf.cultivate.service.FtbCultivatePromotionNewService;
import jnpf.cultivate.service.impl.FtbCultivateFileService;
import jnpf.entity.AttendanceGroup;
import jnpf.entity.StoreEntity;
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
import jnpf.model.vo.UserSalaryHistoryVo;
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.po.org.FtbPositionGradesInfoBoundVO;
import jnpf.model.cultivate.req.exam.QueryCultivateExamReq;
import jnpf.model.cultivate.resp.MyExamListVo;
import jnpf.model.cultivate.resp.UserExamDetailVo;
import jnpf.model.cultivate.vo.course.web.PromotionChannelLearnCourseVO;
import jnpf.model.cultivate.vo.identify.IdentifyApplyInfoApiVo;
import jnpf.model.cultivate.vo.offline.FtbCultivateOfflineFileVO;
import jnpf.model.cultivate.vo.promotion.FtbCultivatePromotionVO;
import jnpf.model.enums.FtbPersonnelsAuditTaskEnum;
import jnpf.model.enums.FtbPersonnelsCofigEnum;
import jnpf.model.personnels.dto.apply.FtbPersonnelsApplyCreateDto;
import jnpf.model.personnels.dto.base.PersonnelsQueryDTO;
import jnpf.model.personnels.dto.regular.FtbPersonnelsForAppQueryDTO;
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.StaffPromotionDto;
import jnpf.model.personnels.dto.staff.roster.WorkerGroupDataDto;
import jnpf.model.personnels.po.FtbPersonnelsPostApply;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.model.personnels.vo.app.FtbPersonnelsBubbleCountVO;
import jnpf.model.personnels.vo.apply.FtbPersonnelsApplyVO;
import jnpf.model.personnels.vo.apply.FtbPersonnelsApplyWithPerVO;
import jnpf.model.personnels.vo.apply.FtbPersonnelsCourseVO;
import jnpf.model.personnels.vo.salary.UserInfoWithSalary;
import jnpf.model.personnels.vo.task.FtbPersonnelsAuditInfoVO;
import jnpf.model.personnels.vo.task.FtbPersonnelsResult;
import jnpf.permission.PositionApi;
import jnpf.permission.RoleApi;
import jnpf.permission.UserApi;
import jnpf.permission.UserPrimaryPositionApi;
import jnpf.permission.dto.SynUserBoundRoleDTO;
import jnpf.permission.dto.UpdateUserManagerBoundDTO;
import jnpf.permission.dto.position.CheckExistByPositionDTO;
import jnpf.permission.dto.relation.BaseUserPrimaryPositionDTO;
import jnpf.permission.dto.role.RemoveUserRolesDTO;
import jnpf.permission.entity.BasePositionGradesEntity;
import jnpf.permission.entity.OrganizeEntity;
import jnpf.permission.entity.PositionEntity;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.model.position.PositionGradesInfoBoundVO;
import jnpf.permission.model.position.PositionGradesInfoVO;
import jnpf.permission.model.position.PositionInfoNewVO;
import jnpf.permission.model.role.RoleListVO;
import jnpf.permission.model.role.UserBoundRolesVO;
import jnpf.personnels.mapper.FtbPersonnelsPostApplyMapper;
import jnpf.personnels.service.*;
import jnpf.personnels.utils.PersonnelOrgUtils;
import jnpf.personnels.utils.PersonnelPerUtils;
import jnpf.salary.QuerySalaryApi;
import jnpf.store.service.StoreService;
import jnpf.util.UserProvider;
import jnpf.util.context.SpringContext;
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.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FtbPersonnelsPostApplyServiceImpl extends ServiceImpl<FtbPersonnelsPostApplyMapper, FtbPersonnelsPostApply> implements FtbPersonnelsPostApplyService {


    @Resource
    private FtbCultivateFileService ftbCultivateFileService;

    @Resource
    private FtbCultivateExamUserService ftbCultivateExamUserService;

    @Resource
    private FtbCultivatePositionIdentifyResultMapper ftbCultivatePositionIdentifyResultMapper;

    @Resource
    private CultivateIdentifyApplyService cultivateIdentifyApplyService;

    @Resource
    private FtbCultivateCourseService ftbCultivateCourseService;

    @Autowired
    private UserApi userApi;

    @Resource
    private PositionApi positionApi;

    @Resource
    private FtbPersonnelsAuditRunTaskService auditRunTaskService;

    @Resource
    private FtbPersonnelsAuditSubConfigService subConfigService;

    @Resource
    public FtbCultivatePromotionMemberMapper memberMapper;

    @Resource
    public PersonnelPerUtils personnelPerUtils;

    @Resource
    private FtbPersonnelsStaffRosterService rosterService;

    @Resource
    private FtbCultivatePromotionNewService promotionNewService;

    @Resource
    private AttendanceGroupApi attendanceGroupApi;

    @Resource
    private AttendanceUserApi attendanceUserApi;

    @Resource
    private  StoreService storeService;

    @Autowired
    FtbPersonnelsSalaryService salaryService;

    @Resource
    PersonnelOrgUtils personnelOrgUtils;

    @Resource
    QuerySalaryApi querySalaryApi;

    @Resource
    FtbCultivatePromotionNewMapper cultivatePromotionNewMapper;

    @Autowired
    RoleApi roleApi;

    @Autowired
    UserPrimaryPositionApi userPrimaryPositionApi;

    @Override
    public PageListVO<FtbPersonnelsApplyVO> getList(PersonnelsQueryDTO dto, CultivatePage cultivatePage) {
        Page<FtbPersonnelsApplyVO> page = cultivatePage.coverCultivatePage();
        UserInfo user = UserProvider.getUser();
        Page<FtbPersonnelsApplyVO> mapperList;
        if ("2".equals(dto.getMyApprovalFlag())) {
            FtbPersonnelsForAppQueryDTO covert = FtbPersonnelsForAppQueryDTO.covert(dto);
            covert.setUserId(user.getUserId());
            covert.setConfigType(FtbPersonnelsCofigEnum.PROMOTION_APPROVAL_CONFIGURATION.getConfigType());
            if (dto.getApprovalStatus() == 0){
                mapperList =baseMapper.listOfDataToBeApproved(page, covert);
            }else {
                mapperList = baseMapper.getApprovalList(page, covert);
            }
        }else {
            // 数据权限orgIds
            List<String> orgIds = personnelPerUtils.obtainPersonnelOrganizationIdDataPermissions();
            if (CollUtil.isNotEmpty(orgIds)){
                dto.setOrgIds(orgIds);
            }
            mapperList  = baseMapper.getListInfo(page, dto);
        }
        // 转换数据
        Map<String, Integer> map = new HashMap<>();
        List<Map<String, String>> postCourseIds = cultivatePromotionNewMapper.doQueryTheLearnedPositionIdFirst(null);
        if (CollUtil.isNotEmpty(postCourseIds)) {
            Map<String, List<String>> postMapIds = postCourseIds.stream().collect(Collectors.toMap(k -> k.get("postId"), v -> List.of(v.get("courseIds").split(","))));
            Set<String> postIds = postMapIds.keySet();
            List<String> userIds = mapperList.getRecords().stream().map(FtbPersonnelsApplyVO::getUserId).collect(Collectors.toList());
            for (String post : postIds) {
                List<String> courseIds = postMapIds.get(post);
                // 查询这个课程是多少人在学习
                // 用户对应的学习记录
                List<FtbPersonnelsCourseVO> courseVOS = cultivatePromotionNewMapper.doQueryTheLearnedPositionIdSecondNew(userIds, courseIds, List.of(1));
                if (CollUtil.isEmpty(courseVOS)) continue;
                Map<String, Integer> userCourseMap = courseVOS.stream().collect(Collectors.toMap(FtbPersonnelsCourseVO::getUserId, FtbPersonnelsCourseVO::getCount, (a, b) -> a));
                for (String userId : userIds) {
                    if (userCourseMap.containsKey(userId) && userCourseMap.get(userId) == courseIds.size()) {
                        if (map.containsKey(userId)) {
                            map.put(userId, map.get(userId) + 1);
                        } else {
                            map.put(userId, 1);
                        }
                    }
                }
            }
        }
        // 用户学习记录
        mapperList.getRecords().forEach(item ->{
            if (map.containsKey(item.getUserId())) item.setNumberOfPositionsStudied(map.get(item.getUserId()));
        });
        return CultivatePage.coverPageList(mapperList);
    }

    @Override
    public PageListVO<FtbPersonnelsApplyVO> getListForApp(FtbPersonnelsForAppQueryDTO dto, CultivatePage cultivatePage) {
        Page<FtbPersonnelsApplyVO> page = cultivatePage.coverCultivatePage();
        //  2.我的审批 3 抄送我的 4 我的申请
        Page<FtbPersonnelsApplyVO> mapperList =null;
        dto.setUserId(UserProvider.getUser().getUserId());
        if (!"4".equals(dto.getFlagByApp())) {
            // 数据权限orgIds
            List<String> orgIds = personnelPerUtils.obtainPersonnelOrganizationIdDataPermissions();
            if (CollUtil.isNotEmpty(orgIds)) {
                dto.setOrgIds(orgIds);
            }
        }
        mapperList = baseMapper.getListForApp(page, dto);
        mapperList.getRecords().forEach(item ->{
            // 查询当前申请时上传的文件信息
            List<FtbCultivateFile> list = ftbCultivateFileService.lambdaQuery().eq(FtbCultivateFile::getBusinessId, item.getId()).list();
            List<FtbCultivateOfflineFileVO> fileVOS = list.stream()
                    .map(FtbCultivateOfflineFileVO::convertFtbCultivateOfflineFileVO).collect(Collectors.toList());
            item.setFiles(fileVOS);
        });
        return CultivatePage.coverPageList(mapperList);
    }

    @Override
    public List<PositionInfoNewVO> queryPostInfoByOrgAndUserId(String userId, String orgId) {
        List<FtbCultivatePromotionVO> promotionVOList = memberMapper.queryPromotionByUserOrOrgId(userId, orgId);
        if (CollUtil.isEmpty(promotionVOList)){
            throw new RuntimeException("当前并未启动晋升通道,无法选择晋升岗位!");
        }
        List<String> postIds = promotionVOList.stream().map(FtbCultivatePromotionVO::getChannelIniPoId).collect(Collectors.toList());
        List<FtbPositionGradesInfoBoundVO> positionGradesInfoBoundVOS = getPositionGradesInfoBoundVOS(userId, orgId);
        List<PositionInfoNewVO> positionInfoNewVOS = postIds.stream().map(id -> {
            PositionInfoNewVO data = null;
            try {
                ActionResult<PositionInfoNewVO> infoNew = positionApi.getInfoNew(id);
                if (infoNew.getCode() == 200) {
                    data = infoNew.getData();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return data;
        }).collect(Collectors.toList());
        Map<String, String> stringStringMap = positionGradesInfoBoundVOS.stream()
                .collect(
                        Collectors.toMap(FtbPositionGradesInfoBoundVO::getPositionId,
                                FtbPositionGradesInfoBoundVO::getPositionGradesId,
                                (a, b) -> a));
        List<PositionInfoNewVO> result = new LinkedList<>();
        for (PositionInfoNewVO positionInfoNewVO : positionInfoNewVOS) {
            List<BasePositionGradesEntity> positionGradesList = positionInfoNewVO.getPositionGradesList();
            // 通过岗位ID获取职等id 进行过滤
            String positionGradesId =stringStringMap.get(positionInfoNewVO.getId());
            if (stringStringMap.containsKey(positionInfoNewVO.getId())) {
                // 通过职等ID过滤已经存在的职等
                List<BasePositionGradesEntity> newPositionGradesList =
                        positionGradesList.stream().filter(item->!item.getId().equals(positionGradesId))
                                .collect(Collectors.toList());

                if (CollUtil.isNotEmpty(newPositionGradesList)){
                    positionInfoNewVO.setPositionGradesList(null);
                    positionInfoNewVO.setPositionGradesList(newPositionGradesList);
                    // 过滤已存在的
                    result.add(positionInfoNewVO);
                }
            }else {
                // 封装每一个不存在的岗位
                result.add(positionInfoNewVO);
            }
        }
        return result;
    }

    @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.setConfigType(FtbPersonnelsCofigEnum.PROMOTION_APPROVAL_CONFIGURATION.getConfigType());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.PENDING.getCode());
            countVO.setPendingCount(baseMapper.listOfDataToBeApproved(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
            countVO.setQuantityUnderCount(baseMapper.getApprovalList(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode());
            countVO.setApprovedCount(baseMapper.getApprovalList(new Page<>(), appQueryDTO).getTotal());
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode());
            countVO.setApprovalFailedCount(baseMapper.getApprovalList(new Page<>(), appQueryDTO).getTotal());
        }else if ("2".equals(flag)){
            appQueryDTO.setFlagByApp("3");
            appQueryDTO.setApprovalStatus(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
            appQueryDTO.init("3",FtbPersonnelsCofigEnum.PROMOTION_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 clearPromotionData(List<String> userIds) {
        LambdaQueryWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.in(FtbPersonnelsPostApply::getUserId,userIds);
        List<FtbPersonnelsPostApply> managements = baseMapper.selectList(wrapper);
        if (CollUtil.isEmpty(managements)){
            return;
        }
        // 清除具有审批数据的数据
        managements.stream().filter(vo-> StringUtils.isNotEmpty(vo.getTaskInfoId()))
                .forEach (item->auditRunTaskService.deleteReviewProcessAndRecords(item.getTaskInfoId(),item.getId()));
        // 晋升数据
        LambdaUpdateWrapper<FtbPersonnelsPostApply> lambdaed = Wrappers.lambdaUpdate();
        lambdaed.in(FtbPersonnelsPostApply::getId,managements.stream().map(FtbPersonnelsPostApply::getId).collect(Collectors.toList()));
        baseMapper.delete(lambdaed);
    }



    @SneakyThrows
    @Override
    @Transactional(rollbackFor = {Exception.class,RuntimeException.class})
    public String initiateAPromotionApplication(FtbPersonnelsApplyCreateDto createDto) {
        String resultStr = "";
        FtbPersonnelsPostApply ftbPersonnelsPostApply = FtbPersonnelsApplyCreateDto.coverFtbPersonnelsApplyVO(createDto);
        LambdaQueryWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsPostApply::getUserId, ftbPersonnelsPostApply.getUserId());
        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        wrapper.in(FtbPersonnelsPostApply::getState, list);
        FtbPersonnelsPostApply postApply = baseMapper.selectOne(wrapper);
        if (ObjectUtil.isNotNull(postApply)) {
            throw new RuntimeException("您上次提交的晋升申请还在审核中,请等待审核完成再提交!");
        }

        // 校验直属主管是否为试岗员工
        if (StringUtils.isNotEmpty(ftbPersonnelsPostApply.getImmediateSuperId())){
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> lambdaed = Wrappers.lambdaQuery();
            lambdaed.eq(FtbPersonnelsStaffRoster::getUserId,ftbPersonnelsPostApply.getImmediateSuperId());
            FtbPersonnelsStaffRoster one = rosterService.getOne(lambdaed);
            if (one.getWorkerStatus().equals("306")) throw new RuntimeException("试岗员工:"+one.getName()+"不能作为直属主管!");
        }
         List<FtbPositionGradesInfoBoundVO> positionGradesInfoBoundVOS =
                getPositionGradesInfoBoundVOS(ftbPersonnelsPostApply.getUserId(), ftbPersonnelsPostApply.getOrgId());
        if (ObjectUtil.isEmpty(positionGradesInfoBoundVOS)) {
            throw new RuntimeException("当前用户未分配岗位,无法进行申请!");
        }
        Set<String> collect = positionGradesInfoBoundVOS.stream().map(FtbPositionGradesInfoBoundVO::getPositionGradesId).collect(Collectors.toSet());
        if (!collect.contains(ftbPersonnelsPostApply.getPostRankId())) {
            throw new RuntimeException("当前申请变更岗位,在个人岗位中不存在请重新选择进行重试!");
        }
        if (StringUtils.isNotEmpty(ftbPersonnelsPostApply.getPromotionReason()) && ftbPersonnelsPostApply.getPromotionReason().length() > 500) {
            throw new RuntimeException("晋升原因过长,不能超过500个字,请修改后重试!");
        }
        if ( (ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId())) &&
                (ftbPersonnelsPostApply.getPostId().equals(ftbPersonnelsPostApply.getPostPromotionId()))
                && (ftbPersonnelsPostApply.getPostRankId()
                .equals(ftbPersonnelsPostApply.getPostRankPromotionId()))){
            throw new RuntimeException("晋升组织岗位职等不能与当前组织岗位职等一致,请重新选择进行重试!");
        }

        List<WorkerGroupDataDto> userList = personnelOrgUtils.getUserOrgBoundInfo(ftbPersonnelsPostApply.getUserId());
        if (CollUtil.isNotEmpty(userList) && userList.size() > 1){
            // 员工所属组织
            for (WorkerGroupDataDto dataDto : userList) {
                // 员工调岗组织岗位 都相同 不能有不同职等
                if ( !(ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId()) &&
                        ftbPersonnelsPostApply.getPostId().equals(ftbPersonnelsPostApply.getPostPromotionId()))
                        && (dataDto.getAffiliatedOrg().equals(ftbPersonnelsPostApply.getOrgCurrentId()) &&
                        dataDto.getAffiliatedPosition().equals(ftbPersonnelsPostApply.getPostPromotionId()))){
                    throw new RuntimeException("您在目标组织中已所属于该岗位，不可重复选择同一组织下相同岗位！");
                }
            }
        }
        // v1.1 添加门店负责人校验
        // 跨组织校验
        if (!ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId())) {
            LambdaQueryWrapper<StoreEntity> storeEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
            storeEntityLambdaQueryWrapper.eq(StoreEntity::getStoreheaduserid, ftbPersonnelsPostApply.getUserId());
            long count = storeService.count(storeEntityLambdaQueryWrapper);
            if (count > 0) return "1";
        }
        FtbPersonnelsResult result = FtbPersonnelsResult.getResult(createDto.getSource(),createDto.getFlag());
        ftbPersonnelsPostApply.setState(result.state);
        ftbPersonnelsPostApply.setSource(result.source);
        // 添加薪资详情
        StaffHomeDto staffHomeDto = rosterService.queryWorkerHomeDetail(ftbPersonnelsPostApply.getUserId());
        // 晋升前薪资覆盖
        if (staffHomeDto != null) ftbPersonnelsPostApply.setCurrentPay(staffHomeDto.getCurrSalary());
        List<FtbPersonnelsSalaryInfo> salaryStructureList = createDto.getSalaryStructureList();
        if (CollUtil.isEmpty(salaryStructureList)  && "1".equals(createDto.getIsAdjustSalary()) ){
            throw new RuntimeException("目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
        }
        Integer isDelete = createDto.getIsDelete();
        if ("1".equals(createDto.getIsAdjustSalary()) && isDelete == null){
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            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) &&  StringUtils.isNotEmpty(data.get(0).getFRemark())) return "5";
            // 没有薪酬默认不做废
            isDelete = 0;
        }
        if ("1".equals(createDto.getIsAdjustSalary()) && CollUtil.isNotEmpty(salaryStructureList)){
            ftbPersonnelsPostApply.setSalaryStructureList(JSONObject.toJSONString(salaryStructureList));
        }

        // 重新申请
        if (StringUtils.isNotEmpty(createDto.getId())){
            // 离职编辑 删除之前的信息
            // 删除上传的文件重新上传
            LambdaUpdateWrapper<FtbCultivateFile> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(FtbCultivateFile::getBusinessId, createDto.getId());
            ftbCultivateFileService.remove(updateWrapper);
            ftbPersonnelsPostApply.setId(createDto.getId());
            baseMapper.updateById(ftbPersonnelsPostApply);
        }else {
            baseMapper.insert(ftbPersonnelsPostApply);
        }
        // 创建审批
        String postApplyId = ftbPersonnelsPostApply.getId();
        UserInfo userInfo = UserProvider.getUser();
        if (ftbPersonnelsPostApply.getUserId().equals(userInfo.getUserId())){
            throw new RuntimeException("无法给自己进行手动晋升!");
        }
        //  手动变更薪资详情
        if (createDto.getIsAdjustSalary().equals("1")){
            UserInfoWithSalary userInfoWithSalary = new UserInfoWithSalary();
            userInfoWithSalary.setRankName(ftbPersonnelsPostApply.getPostRankPromotionName());
            userInfoWithSalary.setRankId(ftbPersonnelsPostApply.getPostRankPromotionId());
            userInfoWithSalary.setFOrgId(ftbPersonnelsPostApply.getOrgCurrentId());
            userInfoWithSalary.setFOrgName(ftbPersonnelsPostApply.getOrgCurrentName());
            userInfoWithSalary.setPostId(ftbPersonnelsPostApply.getPostPromotionId());
            userInfoWithSalary.setPostName(ftbPersonnelsPostApply.getPostPromotionName());
            salaryService.saveTheChangePayInformation(salaryStructureList,
                    ftbPersonnelsPostApply.getUserId(),
                    ftbPersonnelsPostApply.getPayrollEffectiveDate(),
                    userInfoWithSalary,
                    "1",
                    ftbPersonnelsPostApply.getReasonsForSalaryAdjustments(),
                    "3",
                    isDelete,null, "");
        }
        // 晋升通过后，变更当前人员岗位职等，
        UpdateUserManagerBoundDTO updateUserManagerBoundDTO = new UpdateUserManagerBoundDTO();
        String userId = ftbPersonnelsPostApply.getUserId();
        updateUserManagerBoundDTO.setUserId(userId);
        updateUserManagerBoundDTO.setOldOrgId(ftbPersonnelsPostApply.getOrgId());
        updateUserManagerBoundDTO.setOldPositionId(ftbPersonnelsPostApply.getPostId());
        updateUserManagerBoundDTO.setOldPositionGradesId(ftbPersonnelsPostApply.getPostRankId());
        updateUserManagerBoundDTO.setOldManagerId(ftbPersonnelsPostApply.getOldImmediateSuperId());
        updateUserManagerBoundDTO.setOldManagerName(ftbPersonnelsPostApply.getOldImmediateSuperName());
        updateUserManagerBoundDTO.setOrgId(ftbPersonnelsPostApply.getOrgCurrentId());
        updateUserManagerBoundDTO.setPositionId(ftbPersonnelsPostApply.getPostPromotionId());
        updateUserManagerBoundDTO.setPositionGradesId(ftbPersonnelsPostApply.getPostRankPromotionId());
        updateUserManagerBoundDTO.setManagerId(ftbPersonnelsPostApply.getImmediateSuperId());
        updateUserManagerBoundDTO.setManagerName(ftbPersonnelsPostApply.getImmediateSuperName());
        BaseUserPrimaryPositionDTO primaryPositionDTO = new BaseUserPrimaryPositionDTO();
        primaryPositionDTO.setUserId(userId);
        primaryPositionDTO.setOrganizeId(ftbPersonnelsPostApply.getOrgId());
        primaryPositionDTO.setPositionId(ftbPersonnelsPostApply.getPostId());
        primaryPositionDTO.setPositionGradesId(ftbPersonnelsPostApply.getPostRankId());
        primaryPositionDTO.setManagerId(ftbPersonnelsPostApply.getOldImmediateSuperId());
        ActionResult<Boolean> position = userPrimaryPositionApi.isUserUserPrimaryPosition(primaryPositionDTO);
        if (position != null && position.getData()){
            // 更新用户主岗
            BaseUserPrimaryPositionDTO positionDTO = new BaseUserPrimaryPositionDTO();
            positionDTO.setUserId(userId);
            positionDTO.setOrganizeId(ftbPersonnelsPostApply.getOrgCurrentId());
            positionDTO.setPositionId(ftbPersonnelsPostApply.getPostPromotionId());
            positionDTO.setPositionGradesId(ftbPersonnelsPostApply.getPostRankPromotionId());
            positionDTO.setManagerId(ftbPersonnelsPostApply.getImmediateSuperId());
            userPrimaryPositionApi.updateUserPrimaryPosition(positionDTO);
        }
        // 变更角色
        boolean flag = ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId());
        asyncRole(ftbPersonnelsPostApply.getUserId(),flag);
        Boolean b1 = userApi.UserManagerBoundChange(Collections.singletonList(updateUserManagerBoundDTO));
        if (b1 == null ||  !b1){
            throw new RuntimeException("审核变更岗位失败!");
        }
        StaffPromotionDto cover = StaffPromotionDto.cover(ftbPersonnelsPostApply,staffHomeDto.getActualStartDate());
        rosterService.innerPromotion(ftbPersonnelsPostApply.getUserId(),cover, ftbPersonnelsPostApply.getPostPromotionPay());
        // 审核通过考情组变更
        if (StringUtils.isNotEmpty(ftbPersonnelsPostApply.getAttendanceGroup())){
            changeTheExaminationGroup(ftbPersonnelsPostApply.getAttendanceGroup(),ftbPersonnelsPostApply.getUserId());
        }
        rosterService.logout(userInfo.getTenantId(),ftbPersonnelsPostApply.getUserId());
        //通过文件事件监听信息
        SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(FileEventDTO.builder()
                .files(createDto.getFiles())
                .businessTypeID(postApplyId)
                .type(FileEventDTO.FileType.JOB_PROMOTION)
                .build()));
        return resultStr;
    }
    /**
     * 同步用户角色
     *
     * @param userId
     * @param flag 标识是否跨组织
     */
    private void asyncRole(String userId, boolean flag) {
        // 更改用户角色逻辑
        // 2.1 取消调整角色字段，oa审批单同理
        // 2.2 若变更组织，组织角色需清除，全局角色不清除。不变更组
        // 织则不清除角色，维持原样
        ActionResult<List<UserBoundRolesVO>> listActionResult = roleApi.listUsersBound(List.of(userId));
        if (listActionResult == null ) throw new RuntimeException("获取用户角色失败!");
        List<UserBoundRolesVO> data = listActionResult.getData();
        if (CollUtil.isEmpty(data)) return;
        // 查询用户绑定角色
        UserBoundRolesVO userBoundRolesVO = data.stream().filter(item -> userId.equals(item.getId())).findFirst().orElse(new UserBoundRolesVO());
        List<RoleListVO> roleBounds = userBoundRolesVO.getRoleBounds();
        List<String> roleIds;
        if (flag){
            roleIds = roleBounds.stream().map(RoleListVO::getId).collect(Collectors.toList());
        }else {
            // 清除跨组织的角色
            List<String> targetRoleIds = roleBounds.stream().filter(item -> item.getGlobalMark() != 1).map(RoleListVO::getId).collect(Collectors.toList());
            RemoveUserRolesDTO rolesDTO = new RemoveUserRolesDTO();
            rolesDTO.setTargetRoleIds(targetRoleIds);
            rolesDTO.setUserIds(List.of(userId));
            roleApi.removeRoleRelationBatch(rolesDTO);
            roleIds =  roleBounds.stream().filter(item -> item.getGlobalMark() == 1).map(RoleListVO::getId).collect(Collectors.toList());
        }
        // 无角色信息变更
        if (CollUtil.isEmpty(roleIds)) return;
        SynUserBoundRoleDTO dto = new SynUserBoundRoleDTO();
        dto.setUserId(userId);
        dto.setRoleIds(roleIds);
        personnelOrgUtils.sysUserRole(dto);
    }
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public ActionResult<Void> initiateAPromotionApplicationForOA(FtbPersonnelsApplyCreateDto createDto) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg( FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        String filesWithOa = createDto.getFilesWithOa();
        List<FtbCultivateOfflineFileDTO> files = new ArrayList<>();
        if (StringUtils.isNotEmpty(filesWithOa)){
            files = JSONObject.parseArray(filesWithOa, FtbCultivateOfflineFileDTO.class);
        }
        FtbPersonnelsPostApply ftbPersonnelsPostApply = FtbPersonnelsApplyCreateDto.coverFtbPersonnelsApplyVO(createDto);
        FtbPersonnelsResult result1 = FtbPersonnelsResult.getResult(createDto.getSource(),createDto.getFlag());
        ftbPersonnelsPostApply.setState(result1.state);
        ftbPersonnelsPostApply.setSource(result1.source);
        if ( createDto.getSource()  != null && createDto.getSource() !=  0) {
            // 权限用户
            List<String> userIds = personnelPerUtils.obtainPersonnelDataPermissions();
            // 当前人不是本人申请,且权限中有当前可以办理人
            if ((ftbPersonnelsPostApply.getSource() != 0) && (CollUtil.isNotEmpty(userIds) && !userIds.contains(ftbPersonnelsPostApply.getUserId()))) {
                result.setMsg("当前人办理人不具有该员工办理权限!");
                result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                return result;
            }
        }
        if (ftbPersonnelsPostApply.getUserId().equals(ftbPersonnelsPostApply.getImmediateSuperId())){
            result.setMsg("当前申请直属主管不能是办理人!");
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }
        //数据构建
        dataBuilding(ftbPersonnelsPostApply);
        LambdaQueryWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsPostApply::getUserId, ftbPersonnelsPostApply.getUserId());
        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        wrapper.in(FtbPersonnelsPostApply::getState, list);
        FtbPersonnelsPostApply postApply = baseMapper.selectOne(wrapper);
        if (ObjectUtil.isNotNull(postApply)) {
            result.setMsg("您上次提交的晋升申请还在审核中,请等待审核完成再提交!");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }

        // 校验直属主管是否为试岗员工
        if (StringUtils.isNotEmpty(ftbPersonnelsPostApply.getImmediateSuperId())){
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> lambdaed = Wrappers.lambdaQuery();
            lambdaed.eq(FtbPersonnelsStaffRoster::getUserId,ftbPersonnelsPostApply.getImmediateSuperId());
            FtbPersonnelsStaffRoster one = rosterService.getOne(lambdaed);
            if (one.getWorkerStatus().equals("306")){
                result.setMsg("试岗员工:"+one.getName()+"不能作为直属主管!");
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                return result;
            }
        }
        List<FtbPositionGradesInfoBoundVO> positionGradesInfoBoundVOS =
                getPositionGradesInfoBoundVOS(ftbPersonnelsPostApply.getUserId(), ftbPersonnelsPostApply.getOrgId());
        if (ObjectUtil.isEmpty(positionGradesInfoBoundVOS)) {
            result.setMsg("当前用户未分配岗位,无法进行申请!");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }
        Set<String> collect = positionGradesInfoBoundVOS.stream().map(FtbPositionGradesInfoBoundVO::getPositionGradesId).collect(Collectors.toSet());
        if (!collect.contains(ftbPersonnelsPostApply.getPostRankId())) {
            result.setMsg("当前申请变更岗位,在个人岗位中不存在请重新选择进行重试!");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }
        if (StringUtils.isNotEmpty(ftbPersonnelsPostApply.getPromotionReason()) && ftbPersonnelsPostApply.getPromotionReason().length() > 500) {
            result.setMsg("晋升原因过长,不能超过500个字,请修改后重试!");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }
        if ( (ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId())) &&
                (ftbPersonnelsPostApply.getPostId().equals(ftbPersonnelsPostApply.getPostPromotionId()))
                && (ftbPersonnelsPostApply.getPostRankId()
                .equals(ftbPersonnelsPostApply.getPostRankPromotionId()))){
            result.setMsg("晋升组织岗位职等不能与当前组织岗位职等一致,请重新选择进行重试!");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }

        List<WorkerGroupDataDto> userList = personnelOrgUtils.getUserOrgBoundInfo(ftbPersonnelsPostApply.getUserId());
        if (CollUtil.isNotEmpty(userList) && userList.size() > 1){
            // 员工所属组织
            for (WorkerGroupDataDto dataDto : userList) {
                boolean orgBoolean = dataDto.getAffiliatedOrg().equals(ftbPersonnelsPostApply.getOrgCurrentId());
                boolean promotionBoolean = dataDto.getAffiliatedPosition().equals(ftbPersonnelsPostApply.getPostPromotionId());
                boolean orgCurrenBoolean = ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId());
                boolean postBoolean = ftbPersonnelsPostApply.getPostId().equals(ftbPersonnelsPostApply.getPostPromotionId());
                // 员工调岗组织岗位 都相同 不能有不同职等
                if ( !(orgCurrenBoolean && postBoolean) && (orgBoolean && promotionBoolean)){
                    result.setMsg("您在目标组织中已所属于该岗位，不可重复选择同一组织下相同岗位！");
                    result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                    return result;
                }
            }
        }
        // v1.1 添加门店负责人校验
        // 跨组织校验
        if (!ftbPersonnelsPostApply.getOrgId().equals(ftbPersonnelsPostApply.getOrgCurrentId())) {
            LambdaQueryWrapper<StoreEntity> storeEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
            storeEntityLambdaQueryWrapper.eq(StoreEntity::getStoreheaduserid, ftbPersonnelsPostApply.getUserId());
            List<StoreEntity> list1 = storeService.list(storeEntityLambdaQueryWrapper);
            if (!list1.isEmpty()) {
                String storeNames = list1.stream().map(StoreEntity::getStorename).collect(Collectors.joining(","));
                result.setMsg("当前晋升人员为"+storeNames+"门店负责人，请替换后再进行操作！");
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                return result;
            }
        }
        // 添加薪资详情
        List<FtbPersonnelsSalaryInfo> salaryStructureList = createDto.getSalaryStructureList();
        if (CollUtil.isEmpty(salaryStructureList)  && "1".equals(createDto.getIsAdjustSalary()) ){
            result.setMsg( "目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            return result;
        }else if (CollUtil.isNotEmpty(salaryStructureList) && "1".equals(createDto.getIsAdjustSalary())) {
            ftbPersonnelsPostApply.setSalaryStructureList(JSONObject.toJSONString(salaryStructureList));
        }
        ftbPersonnelsPostApply.setVersionNum(1);
        // 修改
        if (StringUtils.isNotEmpty(createDto.getSpecialBusinessId())){
            // 删除上传的文件重新上传
            LambdaUpdateWrapper<FtbCultivateFile> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(FtbCultivateFile::getBusinessId, createDto.getSpecialBusinessId());
            ftbCultivateFileService.remove(updateWrapper);
            ftbPersonnelsPostApply.setId(createDto.getSpecialBusinessId());
            baseMapper.updateById(ftbPersonnelsPostApply);
        }else {
            baseMapper.insert(ftbPersonnelsPostApply);
        }
        // 创建审批
        String postApplyId = ftbPersonnelsPostApply.getId();
        if (result1.source != 2 ){
            // 同步id
            LambdaUpdateWrapper<FtbPersonnelsPostApply> lambdaUpdate = Wrappers.lambdaUpdate();
            lambdaUpdate.eq(FtbPersonnelsPostApply::getId,postApplyId);
            lambdaUpdate.set(FtbPersonnelsPostApply::getTaskInfoId, createDto.getTaskId());
            baseMapper.update(null,lambdaUpdate);
        }
        //通过文件事件监听信息
        SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(FileEventDTO.builder()
                .files(files)
                .businessTypeID(postApplyId)
                .type(FileEventDTO.FileType.JOB_PROMOTION)
                .build()));
        return result;
    }

    private void dataBuilding(FtbPersonnelsPostApply ftbPersonnelsPostApply) {
        // 晋升前
        OrganizeEntity organizeEntity = personnelOrgUtils.queryOrganizeInfo(ftbPersonnelsPostApply.getOrgId());
        if (ObjectUtil.isNotEmpty(organizeEntity))ftbPersonnelsPostApply.setOrgName(organizeEntity.getFullName());
        PositionEntity positionEntity = personnelOrgUtils.queryPosition(ftbPersonnelsPostApply.getPostId());
        if (ObjectUtil.isNotEmpty(positionEntity)) ftbPersonnelsPostApply.setPostName(positionEntity.getFullName());
        PositionGradesInfoVO gradesInfoVO = personnelOrgUtils.queryRank(ftbPersonnelsPostApply.getPostRankId());
        if (ObjectUtil.isNotEmpty(gradesInfoVO))ftbPersonnelsPostApply.setPostRankName(gradesInfoVO.getFullName());
        // 晋升后
        OrganizeEntity organizeEntity1 = personnelOrgUtils.queryOrganizeInfo(ftbPersonnelsPostApply.getOrgCurrentId());
        if (ObjectUtil.isNotEmpty(organizeEntity1))ftbPersonnelsPostApply.setOrgCurrentName(organizeEntity1.getFullName());
        PositionEntity positionEntity1 = personnelOrgUtils.queryPosition(ftbPersonnelsPostApply.getPostPromotionId());
        if (ObjectUtil.isNotEmpty(positionEntity1)) ftbPersonnelsPostApply.setPostPromotionName(positionEntity1.getFullName());
        PositionGradesInfoVO positionGradesInfoVO = personnelOrgUtils.queryRank(ftbPersonnelsPostApply.getPostRankPromotionId());
        if (ObjectUtil.isNotEmpty(positionGradesInfoVO))ftbPersonnelsPostApply.setPostRankPromotionName(positionGradesInfoVO.getFullName());
        if(StringUtils.isNotEmpty(ftbPersonnelsPostApply.getImmediateSuperId())){
            UserEntity userEntity = personnelOrgUtils.queryUserInfo(ftbPersonnelsPostApply.getImmediateSuperId());
            if (ObjectUtil.isNotEmpty(userEntity))ftbPersonnelsPostApply.setImmediateSuperName(userEntity.getRealName());
        }
        StaffHomeDto staffHomeDto = rosterService.queryWorkerHomeDetail(ftbPersonnelsPostApply.getUserId());
        // 工号
        if (ObjectUtil.isNotEmpty(staffHomeDto)){
            ftbPersonnelsPostApply.setJobNumber(staffHomeDto.getWorkerNo());
            ftbPersonnelsPostApply.setSystemWokerId(staffHomeDto.getSystemWokerId());
            ftbPersonnelsPostApply.setCurrentPay(staffHomeDto.getCurrSalary());
        }

    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public ActionResult<Void> auditPromotionPostApplicationWithOA(FtbPersonnelsSalaryAuditDto dto) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg( FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        LambdaQueryWrapper<FtbPersonnelsPostApply> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPersonnelsPostApply::getTaskInfoId,dto.getTaskId());
        FtbPersonnelsPostApply postApply = baseMapper.selectOne(queryWrapper);
        if (ObjectUtil.isEmpty(postApply)){
            result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg( "需要审批的数据不存在,或已经进行审批,请重新提交处理!");
            return result;
        }
        // 校验岗位是否存在
        // 选择通过需要校验组织是否存在
        String businessId = postApply.getId();
        if ("1".equals(dto.getFlag())){
            // 校验岗位是否还存在
            CheckExistByPositionDTO checkExistByPositionDTO = new CheckExistByPositionDTO();
            checkExistByPositionDTO.setOrganizeId(postApply.getOrgCurrentId());
            checkExistByPositionDTO.setPositionId(postApply.getPostPromotionId());
            checkExistByPositionDTO.setPositionGradesId(postApply.getPostRankPromotionId());
            ActionResult<Boolean> booleanActionResult = positionApi.checkExistByPositionMore(checkExistByPositionDTO);
            if (booleanActionResult  == null || !booleanActionResult.getData()){
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                result.setMsg( "该员工晋升后目标岗位不存在，无法继续审批；请选择“不通过”结束审批流程！");
                return result;
            }
        }
        if ("1".equals(dto.getFlag())){
            // 校验岗位是否还存在
            CheckExistByPositionDTO checkExistByPositionDTO = new CheckExistByPositionDTO();
            checkExistByPositionDTO.setOrganizeId(postApply.getOrgId());
            checkExistByPositionDTO.setPositionId(postApply.getPostId());
            checkExistByPositionDTO.setPositionGradesId(postApply.getPostRankId());
            ActionResult<Boolean> booleanActionResult = positionApi.checkExistByPositionMore(checkExistByPositionDTO);
            if (booleanActionResult  == null || !booleanActionResult.getData()){
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                result.setMsg( "该员工的岗位在提交晋升审批后发生了变更，无法继续审批；请选择“不通过”结束审批流程！");
                return result;
            }
        }
        // 通过oa传值进行数据核对
        FtbPersonnelsAuditTaskEnum code = dto.getFlag().equals("0") ? FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED :
                FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED;
        LambdaUpdateWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(FtbPersonnelsPostApply::getState, code.getCode());
        if (ObjectUtil.isNotEmpty(dto.getSalary()) && dto.getSalary().compareTo(BigDecimal.ZERO) > 0){
            wrapper.set(FtbPersonnelsPostApply::getPostPromotionPay,dto.getSalary());
        }
        if (ObjectUtil.isNotEmpty(dto.getDoesTheSalaryComplyWith())){
            wrapper.set(FtbPersonnelsPostApply::getPayCompliance,dto.getDoesTheSalaryComplyWith());
        }
        if (ObjectUtil.isNotEmpty(dto.getPayrollEffectiveDate())){
            wrapper.set(FtbPersonnelsPostApply::getPayrollEffectiveDate,dto.getPayrollEffectiveDate());
        }

        if (StringUtils.isNotEmpty(dto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsPostApply::getSalaryStructure,dto.getSalaryStructure());
        }
        if (StringUtils.isNotEmpty(dto.getReasonsForSalaryAdjustments())){
            wrapper.set(FtbPersonnelsPostApply::getReasonsForSalaryAdjustments,dto.getReasonsForSalaryAdjustments());
        }
        List<FtbPersonnelsSalaryInfo> salaryStructureList1 = dto.getSalaryStructureList();
        if (ObjectUtil.isNotEmpty(dto.getIsAdjustSalary())){
            if (CollUtil.isEmpty(salaryStructureList1)  && "1".equals(dto.getIsAdjustSalary()) ){
                result.setMsg( "目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                return result;
            }
            wrapper.set(FtbPersonnelsPostApply::getIsAdjustSalary,dto.getIsAdjustSalary());
        }
        if(CollUtil.isNotEmpty(salaryStructureList1)){
            wrapper.set(FtbPersonnelsPostApply::getSalaryStructureList,JSONObject.toJSONString(salaryStructureList1));
        }
        wrapper.set(SuperBaseEntity.SuperCUBaseEntity::getLastModifyTime,new Date());
        wrapper.eq(FtbPersonnelsPostApply::getId, businessId);
        baseMapper.update(null,wrapper);
        if (FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode().equals(code.getCode())){
            //  薪资变更
            FtbPersonnelsPostApply thiPostApply = baseMapper.selectById(businessId);
            if ("1".equals(thiPostApply.getIsAdjustSalary())){
                String salaryStructureList = thiPostApply.getSalaryStructureList();
                List<FtbPersonnelsSalaryInfo> salaryInfos = JSONObject.parseArray(salaryStructureList, FtbPersonnelsSalaryInfo.class);
                UserInfoWithSalary userInfoWithSalary = new UserInfoWithSalary();
                userInfoWithSalary.setRankName(thiPostApply.getPostRankPromotionName());
                userInfoWithSalary.setRankId(thiPostApply.getPostRankPromotionId());
                userInfoWithSalary.setFOrgId(thiPostApply.getOrgCurrentId());
                userInfoWithSalary.setFOrgName(thiPostApply.getOrgCurrentName());
                userInfoWithSalary.setPostId(thiPostApply.getPostPromotionId());
                userInfoWithSalary.setPostName(thiPostApply.getPostPromotionName());
                salaryService.saveTheChangePayInformation(salaryInfos,
                        thiPostApply.getUserId(),
                        thiPostApply.getPayrollEffectiveDate(),
                        userInfoWithSalary,
                        "1",
                        thiPostApply.getReasonsForSalaryAdjustments(),
                        "3", 0,null, "");
            }
            LambdaQueryWrapper<FtbPersonnelsPostApply> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(FtbPersonnelsPostApply::getId, businessId);
            FtbPersonnelsPostApply promotionPostApply = baseMapper.selectOne(lambdaQuery);
            // 当前岗位职等
            String postRankId = promotionPostApply.getPostRankId();
            // 晋升岗位职等
            String postRankPromotionId = promotionPostApply.getPostRankPromotionId();
            // 变更用户id
            String userId1 = promotionPostApply.getUserId();
            String orgId = postApply.getOrgId();
            String orgCurrentId = postApply.getOrgCurrentId();
            // 晋升通过后，变更当前人员岗位职等，
            UpdateUserManagerBoundDTO updateUserManagerBoundDTO = new UpdateUserManagerBoundDTO();
            String userId = promotionPostApply.getUserId();
            updateUserManagerBoundDTO.setUserId(userId);
            updateUserManagerBoundDTO.setOldOrgId(orgId);
            updateUserManagerBoundDTO.setOldPositionId(promotionPostApply.getPostId());
            updateUserManagerBoundDTO.setOldPositionGradesId(postRankId);
            updateUserManagerBoundDTO.setOldManagerId(promotionPostApply.getOldImmediateSuperId());
            updateUserManagerBoundDTO.setOldManagerName(promotionPostApply.getOldImmediateSuperName());
            updateUserManagerBoundDTO.setOrgId(orgCurrentId);
            updateUserManagerBoundDTO.setPositionId(promotionPostApply.getPostPromotionId());
            updateUserManagerBoundDTO.setPositionGradesId(postRankPromotionId);
            updateUserManagerBoundDTO.setManagerId(promotionPostApply.getImmediateSuperId());
            updateUserManagerBoundDTO.setManagerName(promotionPostApply.getImmediateSuperName());
            BaseUserPrimaryPositionDTO primaryPositionDTO = new BaseUserPrimaryPositionDTO();
            primaryPositionDTO.setUserId(userId);
            primaryPositionDTO.setOrganizeId(promotionPostApply.getOrgId());
            primaryPositionDTO.setPositionId(promotionPostApply.getPostId());
            primaryPositionDTO.setPositionGradesId(promotionPostApply.getPostRankId());
            primaryPositionDTO.setManagerId(promotionPostApply.getOldImmediateSuperId());
            ActionResult<Boolean> position = userPrimaryPositionApi.isUserUserPrimaryPosition(primaryPositionDTO);
            if (position != null && position.getData()){
                // 更新用户主岗
                BaseUserPrimaryPositionDTO positionDTO = new BaseUserPrimaryPositionDTO();
                positionDTO.setUserId(userId);
                positionDTO.setOrganizeId(promotionPostApply.getOrgCurrentId());
                positionDTO.setPositionId(promotionPostApply.getPostPromotionId());
                positionDTO.setPositionGradesId(promotionPostApply.getPostRankPromotionId());
                positionDTO.setManagerId(promotionPostApply.getImmediateSuperId());
                userPrimaryPositionApi.updateUserPrimaryPosition(positionDTO);
            }
            // 变更角色
            boolean flag = promotionPostApply.getOrgId().equals(promotionPostApply.getOrgCurrentId());
            asyncRole(userId,flag);
            Boolean b1 = userApi.UserManagerBoundChange(Collections.singletonList(updateUserManagerBoundDTO));
            if (b1 == null ||  !b1){
                result.setCode( FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
                result.setMsg( "审核变更岗位失败!");
                return result;
            }
            StaffHomeDto staffHomeDto = rosterService.queryWorkerHomeDetail(userId);
            StaffPromotionDto cover = StaffPromotionDto.cover(promotionPostApply, staffHomeDto.getActualStartDate());
            rosterService.innerPromotion(userId1,cover, promotionPostApply.getPostPromotionPay());
            if (StringUtils.isNotEmpty(promotionPostApply.getAttendanceGroup())) {
                changeTheExaminationGroup(promotionPostApply.getAttendanceGroup(), userId1);
            }
        }
        return result;
    }

    @Override
    public FtbPersonnelsApplyWithPerVO viewPromotionApplications(String id, String appFlag) {
        LambdaQueryWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsPostApply::getId, id);
        FtbPersonnelsPostApply postApply = baseMapper.selectOne(wrapper);
        FtbPersonnelsApplyWithPerVO withPerVO = FtbPersonnelsApplyWithPerVO.cultivatePromotionPostApplyWithPerVO(postApply);
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> staffRosterLambdaQueryWrapper = Wrappers.lambdaQuery();
        staffRosterLambdaQueryWrapper.eq(FtbPersonnelsStaffRoster::getUserId,withPerVO.getUserId());
        FtbPersonnelsStaffRoster one = rosterService.getOne(staffRosterLambdaQueryWrapper);
        withPerVO.setUserName(one.getName());
        withPerVO.setSystemWokerId(one.getSystemWokerId());
        if (StringUtils.isNotEmpty(withPerVO.getAttendanceGroup())){
            AttendanceGroup attendanceGroup = attendanceGroupApi.queryTheNameOfTheAttendanceGroup(withPerVO.getAttendanceGroup());
            if (attendanceGroup != null) withPerVO.setAttendanceGroupName(attendanceGroup.getGroupName());
        }
        // 查询当前申请时上传的文件信息
        LambdaQueryWrapper<FtbCultivateFile> wrapperFile = Wrappers.lambdaQuery();
        wrapperFile.eq(FtbCultivateFile::getBusinessId, postApply.getId());
        LambdaQueryChainWrapper<FtbCultivateFile> fileLambdaQueryChainWrapper = ftbCultivateFileService.lambdaQuery();
        fileLambdaQueryChainWrapper.eq(FtbCultivateFile::getBusinessId, postApply.getId());
        fileLambdaQueryChainWrapper.eq(FtbCultivateFile::getType,FileEventDTO.FileType.JOB_PROMOTION.getType());
        List<FtbCultivateFile> fileLists = ftbCultivateFileService.list(wrapperFile);
        List<FtbCultivateOfflineFileVO> fileVOS = fileLists.stream()
                .map(FtbCultivateOfflineFileVO::convertFtbCultivateOfflineFileVO).collect(Collectors.toList());
        withPerVO.setFiles(fileVOS);
        FtbPersonnelsAuditInfoVO auditInfoVO = subConfigService.queryAuditSubConfig(withPerVO.getOrgId(),FtbPersonnelsCofigEnum.PROMOTION_APPROVAL_CONFIGURATION);
        withPerVO.setAuditInfo(auditInfoVO);
        if (appFlag.equals("1")){
            return withPerVO;
        }
        String userId = withPerVO.getUserId();
        // 考试成绩列表
        QueryCultivateExamReq examReq = new QueryCultivateExamReq();
        examReq.setUserId(userId);
        examReq.setPageSize(-1);
        PageInfo<MyExamListVo> listVoPageInfo = ftbCultivateExamUserService.queryExamList(examReq);
        withPerVO.setAListOfTestScores(listVoPageInfo.getList().stream().map(UserExamDetailVo::covert).collect(Collectors.toList()));
        // 实操鉴定列表
        List<IdentifyApplyInfoApiVo> userIdentifyInfoApi = cultivateIdentifyApplyService.getUserIdentifyInfoWithUserId(userId);
        withPerVO.setListOfPracticalQualifications(userIdentifyInfoApi);
        // 已学习课程列表
        // 当前申请人id
        List<PromotionChannelLearnCourseVO> promotionChannelLearnCourseVOS = ftbCultivateCourseService.promotionPathwayCourses(userId);
        withPerVO.setHaveStudyCourseLists(promotionChannelLearnCourseVOS);

        return withPerVO;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class,RuntimeException.class})
    public void auditPromotionPostApplication(FtbPersonnelsSalaryAuditDto dto) {
        String businessId = dto.getBusinessId();
        FtbPersonnelsPostApply postApply = baseMapper.selectById(businessId);
        // 校验岗位是否存在
        // 选择通过需要校验组织是否存在
        if ("1".equals(dto.getFlag()))verifyTo(postApply);
        if ("1".equals(dto.getFlag()))verifyFrom(postApply);
        // 获取审核节点
        FtbPersonnelsAuditTaskEnum code = auditRunTaskService.performReview(dto);
        LambdaUpdateWrapper<FtbPersonnelsPostApply> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(FtbPersonnelsPostApply::getState, code.getCode());
        if (ObjectUtil.isNotEmpty(dto.getSalary()) && dto.getSalary().compareTo(BigDecimal.ZERO) > 0){
            wrapper.set(FtbPersonnelsPostApply::getPostPromotionPay,dto.getSalary());
        }
        if (ObjectUtil.isNotEmpty(dto.getDoesTheSalaryComplyWith())){
            wrapper.set(FtbPersonnelsPostApply::getPayCompliance,dto.getDoesTheSalaryComplyWith());
        }
        if (ObjectUtil.isNotEmpty(dto.getPayrollEffectiveDate())){
            wrapper.set(FtbPersonnelsPostApply::getPayrollEffectiveDate,dto.getPayrollEffectiveDate());
        }

        if (StringUtils.isNotEmpty(dto.getSalaryStructure())){
            wrapper.set(FtbPersonnelsPostApply::getSalaryStructure,dto.getSalaryStructure());
        }
        List<FtbPersonnelsSalaryInfo> salaryStructureList1 = dto.getSalaryStructureList();
        if (ObjectUtil.isNotEmpty(dto.getIsAdjustSalary())){
            if (CollUtil.isEmpty(salaryStructureList1)  && "1".equals(dto.getIsAdjustSalary()) ){
                throw new RuntimeException("目标岗位暂无薪资结构，无法进行薪酬调整；建议选择是否调整薪酬为“否”！");
            }
            wrapper.set(FtbPersonnelsPostApply::getIsAdjustSalary,dto.getIsAdjustSalary());
        }
        if(CollUtil.isNotEmpty(salaryStructureList1)){
            wrapper.set(FtbPersonnelsPostApply::getSalaryStructureList,JSONObject.toJSONString(salaryStructureList1));
        }
        wrapper.set(SuperBaseEntity.SuperCUBaseEntity::getLastModifyTime,new Date());
        wrapper.eq(FtbPersonnelsPostApply::getId, businessId);
        baseMapper.update(null,wrapper);
        if (FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode().equals(code.getCode())){
            LambdaQueryWrapper<FtbPersonnelsPostApply> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(FtbPersonnelsPostApply::getId, businessId);
            FtbPersonnelsPostApply promotionPostApply = baseMapper.selectOne(lambdaQuery);
            // 当前岗位职等
            String postRankId = promotionPostApply.getPostRankId();
            // 晋升岗位职等
            String postRankPromotionId = promotionPostApply.getPostRankPromotionId();
            // 变更用户id
            String userId1 = promotionPostApply.getUserId();
            String orgId = postApply.getOrgId();
            String orgCurrentId = postApply.getOrgCurrentId();
            // 晋升通过后，变更当前人员岗位职等，
            UpdateUserManagerBoundDTO updateUserManagerBoundDTO = new UpdateUserManagerBoundDTO();
            String userId = promotionPostApply.getUserId();
            updateUserManagerBoundDTO.setUserId(userId);
            updateUserManagerBoundDTO.setOldOrgId(orgId);
            updateUserManagerBoundDTO.setOldPositionId(promotionPostApply.getPostId());
            updateUserManagerBoundDTO.setOldPositionGradesId(postRankId);
            updateUserManagerBoundDTO.setOldManagerId(promotionPostApply.getOldImmediateSuperId());
            updateUserManagerBoundDTO.setOldManagerName(promotionPostApply.getOldImmediateSuperName());
            updateUserManagerBoundDTO.setOrgId(orgCurrentId);
            updateUserManagerBoundDTO.setPositionId(promotionPostApply.getPostPromotionId());
            updateUserManagerBoundDTO.setPositionGradesId(postRankPromotionId);
            updateUserManagerBoundDTO.setManagerId(promotionPostApply.getImmediateSuperId());
            updateUserManagerBoundDTO.setManagerName(promotionPostApply.getImmediateSuperName());
            // 角色
            String roleId = promotionPostApply.getRoleId();
            SynUserBoundRoleDTO synUserBoundRoleDTO = new SynUserBoundRoleDTO();
            synUserBoundRoleDTO.setUserId(userId);
            if (StringUtils.isNotEmpty(roleId)){
                String[] split = roleId.split(",");
                synUserBoundRoleDTO.setRoleIds(List.of(split));
            }
            Boolean b = userApi.synchronousUserBoundRole(synUserBoundRoleDTO);
            if (b == null || !b){
                throw new RuntimeException("审核角色变更失败变更失败!");
            }
            Boolean b1 = userApi.UserManagerBoundChange(Collections.singletonList(updateUserManagerBoundDTO));
            if (b1 == null ||  !b1){
                throw new RuntimeException("审核变更岗位失败!");
            }
            StaffHomeDto staffHomeDto = rosterService.queryWorkerHomeDetail(userId);
            StaffPromotionDto cover = StaffPromotionDto.cover(promotionPostApply, staffHomeDto.getActualStartDate());
            rosterService.innerPromotion(userId1,cover, promotionPostApply.getPostPromotionPay());
            if (StringUtils.isNotEmpty(promotionPostApply.getAttendanceGroup())) {
                changeTheExaminationGroup(promotionPostApply.getAttendanceGroup(), userId1);
            }
            //  薪资变更
            FtbPersonnelsPostApply thiPostApply = baseMapper.selectById(businessId);
            if ("1".equals(thiPostApply.getIsAdjustSalary())){
                String salaryStructureList = thiPostApply.getSalaryStructureList();
                List<FtbPersonnelsSalaryInfo> salaryInfos = JSONObject.parseArray(salaryStructureList, FtbPersonnelsSalaryInfo.class);
                UserInfoWithSalary userInfoWithSalary = new UserInfoWithSalary();
                userInfoWithSalary.setRankName(postApply.getPostRankPromotionName());
                userInfoWithSalary.setRankId(postApply.getPostRankPromotionId());
                userInfoWithSalary.setFOrgId(postApply.getOrgCurrentId());
                userInfoWithSalary.setFOrgName(postApply.getOrgCurrentName());
                userInfoWithSalary.setPostId(postApply.getPostPromotionId());
                userInfoWithSalary.setPostName(postApply.getPostPromotionName());
                salaryService.saveTheChangePayInformation(salaryInfos,
                        thiPostApply.getUserId(),
                        thiPostApply.getPayrollEffectiveDate(),
                        userInfoWithSalary,
                        "1",
                        "晋升调薪",
                        "3", 0,null, "");
            }
        }
    }

    /**
     * 校验岗位是否存在
     * @param postApply
     */
    private void verifyTo(FtbPersonnelsPostApply postApply) {

    }
    /**
     * 校验岗位是否存在
     * @param postApply
     */
    private void verifyFrom(FtbPersonnelsPostApply postApply) {
        // 校验岗位是否还存在
        CheckExistByPositionDTO checkExistByPositionDTO = new CheckExistByPositionDTO();
        checkExistByPositionDTO.setOrganizeId(postApply.getOrgId());
        checkExistByPositionDTO.setPositionId(postApply.getPostId());
        checkExistByPositionDTO.setPositionGradesId(postApply.getPostRankId());
        ActionResult<Boolean> booleanActionResult = positionApi.checkExistByPositionMore(checkExistByPositionDTO);
        if (booleanActionResult  == null || !booleanActionResult.getData()){
            throw new RuntimeException("该员工的岗位在提交晋升审批后发生了变更，无法继续审批；请选择“不通过”结束审批流程！");
        }
    }

    /**
     * 变更考情组
     * @param groupId
     * @param userId1
     */
    private void changeTheExaminationGroup(String groupId, String userId1) {
        // 变更考情组
        GroupUpdateByUserDTO groupUpdateByUserDTO = new GroupUpdateByUserDTO();
        groupUpdateByUserDTO.setUserIds(Collections.singletonList(userId1));
        groupUpdateByUserDTO.setType(4);
        groupUpdateByUserDTO.setTenantId(UserProvider.getUser().getTenantId());
        groupUpdateByUserDTO.setToGroupId(groupId);
        attendanceUserApi.groupUpdateByPersonnel(groupUpdateByUserDTO);
    }


    /**
     * 过滤当前组织用户
     * @param userId
     * @param orgId
     * @return
     */
    @NotNull
    public List<FtbPositionGradesInfoBoundVO> getPositionGradesInfoBoundVOS(String userId, String orgId) {
        List<PositionGradesInfoBoundVO> orgPositionInfoList = positionApi.getOrgPositionInfoList(userId);
        List<FtbPositionGradesInfoBoundVO> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(orgPositionInfoList)){
            orgPositionInfoList.forEach(item->{
                FtbPositionGradesInfoBoundVO post = new  FtbPositionGradesInfoBoundVO();
                if (CollUtil.isEmpty(item.getOrganizeIds())){
                    return;
                }
                List<String> organizeIds = item.getOrganizeIds();
                List<String> organizeNames = item.getOrganizeNames();
                for (int i=0; i < organizeIds.size();i++) {
                    if (organizeIds.get(i).equals(orgId)) {
                        post.setOrganizeId(organizeIds.get(i));
                        post.setOrganizeName(organizeNames.get(i));
                        BeanUtil.copyProperties(item,post);
                        list.add(post);
                    }
                }
            });
        }
        return list;
    }
}
