package com.kingdee.eas.custom.recuritment.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.json.JSONTokener;
import com.kingdee.bos.metadata.entity.*;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.basedata.hraux.*;
import com.kingdee.eas.basedata.org.HROrgUnitInfo;
import com.kingdee.eas.basedata.person.BloodType;
import com.kingdee.eas.basedata.person.Genders;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.csinterface.agent.service.base.util.DateTimeUtils;
import com.kingdee.eas.custom.beisen.utils.BeisenApiClient;
import com.kingdee.eas.custom.beisen.utils.BeisenParam;
import com.kingdee.eas.custom.beisen.utils.BeisenParamByProperties;
import com.kingdee.eas.custom.recuritment.ApplicantBeisenCollection;
import com.kingdee.eas.custom.recuritment.ApplicantBeisenFactory;
import com.kingdee.eas.custom.recuritment.ApplicantBeisenInfo;
import com.kingdee.eas.custom.recuritment.IApplicantBeisen;
import com.kingdee.eas.custom.recuritment.bizEnum.ExecuteResultEnum;
import com.kingdee.eas.custom.recuritment.entity.BackInfoTableHeader;
import com.kingdee.eas.custom.recuritment.utils.AttachmentUtils;
import com.kingdee.eas.custom.recuritment.utils.InitialValueUtils;
import com.kingdee.eas.hr.base.IRelation;
import com.kingdee.eas.hr.base.RelationCollection;
import com.kingdee.eas.hr.base.RelationFactory;
import com.kingdee.shr.base.syssetting.app.osf.OSFAppUtil;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.recuritment.*;
import com.kingdee.shr.recuritment.service.SelectNextStageService;
import com.kingdee.util.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import org.apache.logging.log4j.util.TriConsumer;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class RecuritmentFacadeControllerBean extends AbstractRecuritmentFacadeControllerBean {
    private static final Logger logger = Logger.getLogger(RecuritmentFacadeControllerBean.class);


    // 北京时区/shanghai时区
//    private static final ZoneId BEIJING_ZONE = ZoneId.of("Asia/Shanghai");

    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    Map<String, String> configMap = new HashMap<>();
    private Properties propt = new Properties();//共用参数
    //背景调查表头字段
    JSONObject json = new JSONObject();
    //背景调查表头ID
    String applyIdNumber = "";

    /**
     * @throws IOException
     */
    public RecuritmentFacadeControllerBean() throws IOException {
        String filePath = System.getProperty("EAS_HOME") + "/server/properties/beisen/beisenConfig.properties";
        try (InputStreamReader reader = new InputStreamReader(new FileInputStream(filePath), "UTF-8")) {
            this.propt.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("未找到" + filePath + "配置文件。");
            throw e;
        }
        Set<Map.Entry<Object, Object>> set = this.propt.entrySet();
        for (Map.Entry<Object, Object> entry : set) {
            configMap.put((String) entry.getKey(), (String) entry.getValue());
        }
        try {

            // 使用Files.readAllBytes读取文件内容，然后转换为字符串
            byte[] bytes = Files.readAllBytes(Paths.get(System.getProperty("EAS_HOME") + "/server/properties/beisen/backInfoTableHeader.json"));
            String content = new String(bytes);
            // 使用JSONTokener解析JSON内容
            JSONTokener tokener = new JSONTokener(content);
            com.kingdee.bos.json.JSONArray array = (com.kingdee.bos.json.JSONArray) tokener.nextValue();
            for (int i = 0; i < array.length(); i++) {
                com.kingdee.bos.json.JSONObject jsonObject = array.getJSONObject(i);
                String title = jsonObject.getString("title");
                String id = jsonObject.getString("id");
                boolean isStorage = jsonObject.getBoolean("isStorage");
                json.put(id, new BackInfoTableHeader(title, id, isStorage));
                if ("申请ID".equals(title)) {
                    applyIdNumber = id;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步北森简历和附件
     *
     * @param ctx
     * @param billId 单据ID
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _syncBeisenResume(Context ctx, String billId) throws BOSException, EASBizException {
        super._syncBeisenResume(ctx, billId);
        IResumeBaseRec iResumeBaseRec = ResumeBaseRecFactory.getLocalInstance(ctx);

        logger.error("billId" + billId);
        //北森应聘者
        IApplicantBeisen iApplicantBeisen = ApplicantBeisenFactory.getLocalInstance(ctx);
        FilterInfo filterInfo = new FilterInfo();
        FilterItemCollection filterItems = filterInfo.getFilterItems();
        if (!StringUtils.isEmpty(billId)) {
            filterItems.add(new FilterItemInfo("id", billId));
        } else {
            filterItems.add(new FilterItemInfo("syncStatus", "0"));
        }
        EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, null, null);
        ApplicantBeisenCollection applicantBeisenCollection = iApplicantBeisen.getApplicantBeisenCollection(entityViewInfo);
        //同步结果
        int errorSize = 0;
        int successSize = 0;
        Map msgMap = new HashMap();
        for (int i = 0; i < applicantBeisenCollection.size(); i++) {
            ApplicantBeisenInfo applicantBeisenInfo = applicantBeisenCollection.get(i);
            //申请id
            String applyId = applicantBeisenInfo.getApplyId();
            //应聘者id
            String candidateId = applicantBeisenInfo.getCandidateId();
            try {
                ResumeBaseRecCollection collection = iResumeBaseRec.getResumeBaseRecCollection("select * ,resumeState.number where applyId = '" + applyId + "'");
                // 1. 获取简历基础信息
                //ResumeBaseRecInfo resumeInfo = collection.get(0);
                ResumeBaseRecInfo resumeInfo = null;
                if (!collection.isEmpty()) {
                    resumeInfo = collection.get(0);
                    if (!"0001".equals(resumeInfo.getResumeState().getNumber())) {
                        // 非待筛选不同步
                        continue;
                    }
                } else {
                    resumeInfo = new ResumeBaseRecInfo();
                    resumeInfo.put("applyId", applyId);
                    resumeInfo.put("candidateId", candidateId);
                }
                //通过申请ID获取招聘需求
                RecuritmentDemandInfo recuritmentDemandInfo = getRecuritmentByApplyId(ctx, applyId);
                //招聘需求
                resumeInfo.setRecuritmentDemand(recuritmentDemandInfo);
                //招聘职位
                resumeInfo.setDepartment(recuritmentDemandInfo.getDepartment());
                //招聘部门
                resumeInfo.setRecuritPosition(recuritmentDemandInfo.getRecuritPosition());
                //北森应聘者-需求管理
                applicantBeisenInfo.setRecuritment(recuritmentDemandInfo);
                //招聘需求名称
                //applicantBeisenInfo.setRecuritmentName(recuritmentDemandInfo.getPositionName());
                // 2. 获取  标准简历数据
                JSONObject resumeJson = getResumeByApplyId(applyId);
                logger.error("resumeJson--" + resumeJson);
                Integer code = resumeJson.getInteger("code");
                if (200 == code) {
                    JSONObject data = resumeJson.getJSONObject("data");
                    // 3. 处理简历各部分数据
                    Map<String, String> mapData = processResumeSections(ctx, data, resumeInfo);
                    //北森应聘者--应聘者名称
                    applicantBeisenInfo.setCandidateName(mapData.get("name"));
                    //删除附件信息
                    String where = "where boid = '" + resumeInfo.getId().toString() + "' and (attachment.name like '%标准简历%' or attachment.name like '%面试评价%' or attachment.name like '%原始简历%' )";
                    AttachmentUtils.deleteAttachment(ctx, where);
                    // 根据申请Id获取并处理简历文件
                    processResumeFile(applyId, ctx, resumeInfo, "标准简历");
                    // 获取并处理面试评价文件
                    processResumeFile(applyId, ctx, resumeInfo, "面试评价");
                    // 获取并处理原始简历文件
                    processResumeFile(applyId, ctx, resumeInfo, "原始简历");
                    // 获取并处理背调信息文件
                    processResumeFile(applyId, ctx, resumeInfo, "背景调查审批表");
                    //生成录用报批
                    //String errorMsg = saveRecApproval(ctx, mapData);
                    String serviceName = "generateHireApprovalService";
                    Map param = new HashMap();
                    param.put("resumeBaseRecId", mapData.get("resumeBaseRecId").toString());
                    String errorMsg = (String) OSFAppUtil.callService(ctx, serviceName, param);
                    //String errorMsg = null;
                    if (com.kingdee.bos.rabbitmq.util.StringUtils.isEmpty(errorMsg)) {
                        //修改录用报批数据
                        updateApproval(ctx, mapData, applyId);
                        //修复简历数据
                        updateResumeBaseRe(ctx, iResumeBaseRec, mapData.get("resumeBaseRecId").toString());
                        //中间表成功信息
                        applicantBeisenInfo.setSyncResult("同步成功!");
                        applicantBeisenInfo.setSyncStatus(ExecuteResultEnum.SUCCESS);
                        successSize++;
                        //返回给北森信息
                        pushMessageToBeisen(applyId, "同步成功");
                    } else {
                        throw new BOSException(errorMsg.toString());
                    }
                } else {
                    throw new BOSException(resumeJson.getString("message"));
                }
                iApplicantBeisen.save(applicantBeisenInfo);
            } catch (Exception e) {
                e.printStackTrace();
                pushMessageToBeisen(applyId, e.getMessage());
                applicantBeisenInfo.setSyncStatus(ExecuteResultEnum.ERROR);
                applicantBeisenInfo.setSyncResult("简历处理失败: " + e.getMessage());
                iApplicantBeisen.save(applicantBeisenInfo);
                errorSize++;
                logger.error("简历处理失败: " + e.getMessage(), e);
                msgMap.put("error", e.getMessage());
            }
        }
        logger.error("成功条数" + successSize);
        logger.error("失败条数" + errorSize);
        msgMap.put("successSize", successSize);
        msgMap.put("errorSize", errorSize);
        //return msgMap;
    }


    /**
     * 修复简历数据
     *
     * @param ctx
     * @param iResumeBaseRec
     * @param resumeBaseRecId
     * @throws BOSException
     * @throws EASBizException
     */
    public void updateResumeBaseRe(Context ctx, IResumeBaseRec iResumeBaseRec, String resumeBaseRecId) throws BOSException, EASBizException {
        ResumeBaseRecInfo resumeBaseRecInfo = iResumeBaseRec.getResumeBaseRecInfo(new ObjectUuidPK(resumeBaseRecId));
        IWorkingExp iWorkingExp = WorkingExpFactory.getLocalInstance(ctx);
        WorkingExpCollection workingExpColl = iWorkingExp.getWorkingExpCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "' order by dateEnd desc");
        if (!workingExpColl.isEmpty()) {
            WorkingExpInfo workingExpInfo = workingExpColl.get(0);
            //职位
            resumeBaseRecInfo.setLastJob(workingExpInfo.getPosition());
            //公司
            resumeBaseRecInfo.setLastCompany(workingExpInfo.getCompany());
            //行业
            resumeBaseRecInfo.setLastIndustry(workingExpInfo.getIndustry());
        }
        SelectorItemCollection sic = new SelectorItemCollection();
        sic.add("lastJob");
        sic.add("lastCompany");
        sic.add("lastIndustry");
        iResumeBaseRec.updatePartial(resumeBaseRecInfo, sic);
    }

    /**
     * 修改录用报批数据
     *
     * @param ctx
     * @param mapData
     */
    public void updateApproval(Context ctx, Map<String, String> mapData, String applyId) throws BOSException, EASBizException, IOException {
        logger.error("updateApproval--");
        //简历ID
        String resumeBaseRecId = mapData.get("resumeBaseRecId");
        logger.error("简历ID" + resumeBaseRecId);
        //获取录用报批 通过结束日期排序 获取最高学历
        IRecApproval iRecApproval = RecApprovalFactory.getLocalInstance(ctx);
        RecApprovalCollection recApprovalCollection = iRecApproval.getRecApprovalCollection("where resumeBaseRec = '" + resumeBaseRecId + "'");
        if (recApprovalCollection.isEmpty()) {
            throw new BOSException("未查询到录用报批数据！");
        }
        SelectorItemCollection sic = new SelectorItemCollection();
        sic.add("firsteducation");
        sic.add("firstspeciality");
        sic.add("firstschool");
        sic.add("personalScreening");
        RecApprovalInfo recApprovalInfo = recApprovalCollection.get(0);
        //查询简历-教育经历数据
        IEducationExpREC iEducationExpREC = EducationExpRECFactory.getLocalInstance(ctx);
        EducationExpRECCollection educationExpRECCollection = iEducationExpREC.getEducationExpRECCollection("where resumeBase = '" + resumeBaseRecId + "' order by dateEnd desc");
        if (!educationExpRECCollection.isEmpty()) {
            EducationExpRECInfo educationExpRECInfo = educationExpRECCollection.get(0);
            //第一学历
            recApprovalInfo.put("firsteducation", educationExpRECInfo.getDegreeF7().getId());
            //专业
            recApprovalInfo.put("firstspeciality", educationExpRECInfo.getMajor());
            //毕业院校
            recApprovalInfo.put("firstschool", educationExpRECInfo.getSchool());
            iRecApproval.updatePartial(recApprovalInfo, sic);
        }
        //背调信息
        String reportId = configMap.get("reportId");
        String param = "?page=1&pageSize=100&reportId=" + reportId;
        BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
        logger.error("updateApproval--param--" + param);
        JSONObject jsonObject = beisenApiClient.callGetApi(BeisenParam.GET_GRIDDATA + param, new JSONObject());
        //JSONObject jsonObject = beisenApiClient.callGetApi("https://openapi.italent.cn/Ocean/api/v2/Reports/GridData" + param, new JSONObject());
        logger.error("updateApproval--jsonObject--" + jsonObject);
        if (jsonObject.getInteger("code") == 200) {
            JSONObject data = jsonObject.getJSONObject("data");
            JSONArray datas = data.getJSONArray("datas");
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < datas.size(); i++) {
                JSONObject datasJSONObject = datas.getJSONObject(i);
                logger.error("updateApproval--datasJSONObject--" + datasJSONObject);
                logger.error("updateApproval--json--" + json);
                logger.error("updateApproval--applyIdNumber--" + applyIdNumber);
                //判断申请ID是否一致
                if (datasJSONObject.getString(applyIdNumber).equals(applyId)) {
                    sb.append(datas.size() > 1 ? ("背调信息" + (i + 1) + "\n") : "");
                    for (String key : datasJSONObject.keySet()) {
                        if (json.containsKey(key)) {
                            //获取表头
                            BackInfoTableHeader backInfoTableHeader = (BackInfoTableHeader) json.get(key);
                            String title = backInfoTableHeader.getTitle();
                            String id = backInfoTableHeader.getId();
                            boolean isStorage = backInfoTableHeader.isStorage();
                            //获取值
                            String value = datasJSONObject.getString(id);
                            if (isStorage) {
                                sb.append("\t").append(title).append("：").append(value).append("\n");
                            }
                        }
                    }
                }
            }
            recApprovalInfo.setPersonalScreening(sb.toString());
            iRecApproval.updatePartial(recApprovalInfo, sic);
        }
    }

    /**
     * 自动生成录用报批
     * 第二次调整新增代码
     *
     * @param ctx
     * @param mapData
     * @return
     * @throws SHRWebException
     * @throws BOSException
     * @throws EASBizException
     */
    public String saveRecApproval(Context ctx, Map mapData) throws SHRWebException, BOSException, EASBizException {
        IResumeState iResumeState = ResumeStateFactory.getLocalInstance(ctx);
        //"0009" 待报批  录用报批状态
        ResumeStateInfo resumeStateInfo = iResumeState.getResumeStateInfo("where number = '0009'");
        String resumeBaseRecId = mapData.get("resumeBaseRecId").toString();
        String resumeStateId = resumeStateInfo.getId().toString();
        String errorMsg = SelectNextStageService.getInstance().dealNext(ctx, resumeBaseRecId, resumeStateId, "resumeList");
        //String errorMsg = SelectNextStageUtils.getInstance().dealNext(ctx, resumeBaseRecId, resumeStateId, "resumeList");
        logger.error("errorMsg--" + errorMsg);
        return errorMsg;
    }

    /**
     * 通过申请ID获取需求管理
     *
     * @param applyId
     */
    public RecuritmentDemandInfo getRecuritmentByApplyId(Context ctx, String applyId) throws IOException, BOSException {
        BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
        JSONObject pamas = new JSONObject();
        JSONArray applyIds = new JSONArray();
        applyIds.add(applyId);
        pamas.put("applyIds", applyIds);
        String jobId = "";
        //根据申请ID获取申请信息
        JSONObject applyJson = beisenApiClient.callApi(BeisenParam.GET_APPLYLIST_APPLYID, pamas);
        logger.error("applyJson--" + applyJson);
        if (200 == applyJson.getInteger("code")) {
            JSONArray data = applyJson.getJSONArray("data");
            JSONObject applyData = data.getJSONObject(0);
            //职位ID
            jobId = applyData.getString("jobId");
        } else {
            throw new BOSException("根据申请ID获取申请信息失败,原因:" + applyJson.get("message"));
        }
        logger.error("jobId--" + jobId);
        //根据ID获取获取数据单条
        JSONObject entityPamas = new JSONObject();
        entityPamas.put("id", jobId);
        entityPamas.put("metaObjectName", "Recruitment.Job");
        JSONObject entity = beisenApiClient.callApi(BeisenParam.GET_ENTITY, entityPamas);
        logger.error("entity--" + entity);
        if (200 != entity.getInteger("code")) {
            throw new BOSException("根据ID获取获取数据单条失败,原因:" + entity.get("message"));
        }
        JSONObject entityData = entity.getJSONObject("data");
        //根据招聘需求ID获取招聘需求
        JSONObject columns = entityData.getJSONObject("columns");
        JSONObject recruit = columns.getJSONObject("RecruitRequirementIds");
        if (recruit == null) {
            throw new BOSException("未查询到需求IDRecruitRequirementIds");
        }
        String recruitRequirementId = recruit.getString("value");
        //未查询到北森的该人员招聘需求
        if (com.kingdee.bos.rabbitmq.util.StringUtils.isEmpty(recruitRequirementId)) {
            throw new BOSException("通过applyId[" + applyId + "]未查询到招聘需求！");
        }
        logger.error("requirementId--" + recruitRequirementId);
        //根据需求ID获取招聘需求
        JSONArray items = new JSONArray();
        items.add(recruitRequirementId);
        JSONObject requirements = beisenApiClient.callApi(BeisenParam.GET_REQUIREMENTS, items);
        logger.error("requirements--" + requirements);
        if (200 != requirements.getInteger("code")) {
            throw new BOSException("根据需求ID获取招聘需求失败,原因:" + entity.get("message"));
        }
        JSONArray data = requirements.getJSONArray("data");
        JSONObject dataJson = data.getJSONObject(0);
        //招聘需求
        IRecuritmentDemand iRecuritmentDemand = RecuritmentDemandFactory.getLocalInstance(ctx);
        //招聘需求
        RecuritmentDemandCollection recuritmentDemandCollection = iRecuritmentDemand.getRecuritmentDemandCollection("where requirementId='" + recruitRequirementId + "'");
        //shr未查询到对应的招聘需求
        if (recuritmentDemandCollection.isEmpty()) {
            //String message = "sHR未查询到对应的招聘需求，北森需求ID:" + recruitRequirementId + "，需求名称：" + dataJson.getString("name");;
            // 推送未查询到招聘需求消息至北森
            //pushMessageToBeisen(applyId, configMap.get("syncToBsErrorMsg"));
            //pushMessageToBeisen(applyId, "显示匹配不上金蝶原始需求单据");
            throw new BOSException("sHR未查询到对应的招聘需求，北森需求名称：" + dataJson.getString("name") + "，北森需求ID：" + recruitRequirementId);
        }
        //成功則修改北森字段为空
        //pushMessageToBeisen(applyId, "成功");
        return recuritmentDemandCollection.get(0);
    }


    /**
     * 推送消息至北森
     *
     * @param applyId 申请ID
     * @param message 消息
     */
    public void pushMessageToBeisen(String applyId, String message) throws BOSException {
        try {

            BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
            //POST_UPDATEAPPLYLIST 更新申请信息
            JSONObject pamas = new JSONObject();
            JSONArray applyList = new JSONArray();
            JSONObject pama = new JSONObject();
            JSONObject fieldValues = new JSONObject();
            //测试环境：extjianlitongbujieguo_433899_1252390002
            //正式环境：extjianlitongbujieguo_614492_1252390002
            fieldValues.put(configMap.get("syncToErrorBS"), message);//是否同步成功
            pama.put("fieldValues", fieldValues);
            pama.put("applyId", applyId);
            applyList.add(pama);
            pamas.put("applyList", applyList);
            logger.error("pushMessageToBeisen--pamas--" + pamas);
            JSONObject result = beisenApiClient.callApi(BeisenParam.POST_UPDATEAPPLYLIST, pamas);
            logger.error("pushMessageToBeisen--result--" + result);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BOSException(e);
        }
    }


    /**
     * 处理简历文件或面试评价文件
     *
     * @param applyId    申请ID
     * @param ctx        上下文
     * @param resumeInfo 简历信息
     * @param fileType   文件类型("标准简历"或"面试评价")
     */
    private void processResumeFile(String applyId, Context ctx, ResumeBaseRecInfo resumeInfo, String fileType) {
        logger.error("processResumeFile--");
        //是否是背景信息
        boolean isOrigin = false;
        try {
            // 根据文件类型获取对应的文件信息
            //JSONObject fileInfo = "标准简历".equals(fileType) ? getStandardResumeFileUrlByApplyId(applyId) : getInterviewEvaluationFile(applyId);
            JSONObject fileInfo = null;
            String param = "?applyId=" + applyId;
            BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
            if ("标准简历".equals(fileType)) {
                //fileInfo = getStandardResumeFileUrlByApplyId(applyId);
                fileInfo = beisenApiClient.callGetApi(BeisenParam.GET_STANDERDRESUMEFILURLBYAPPLYID + param, new JSONObject());
            } else if ("面试评价".equals(fileType)) {
                //fileInfo = getInterviewEvaluationFile(applyId);
                fileInfo = beisenApiClient.callGetApi(BeisenParam.GET_INTERVIEWEVALUATIONFILE + param, new JSONObject());
            } else if ("原始简历".equals(fileType)) {
                fileInfo = beisenApiClient.callGetApi(BeisenParam.GET_ORIGINRESUMEBYAPPLYID + param, new JSONObject());
            } else if ("背景调查审批表".equals(fileType)) {
                param = "?applyId=" + applyId + "&supportManualCreate=true";
                String GET_BACKGROUNDINVESTIGATIONBYAPPLYID = "https://openapi.italent.cn/RecruitV6/api/v1/Investigation/GetBackgroundInvestigationByApplyId";
                //背景调查附件单独处理
                //fileInfo = beisenApiClient.callGetApi(BeisenParam.GET_BACKGROUNDINVESTIGATIONBYAPPLYID + param, new JSONObject());
                fileInfo = beisenApiClient.callGetApi(GET_BACKGROUNDINVESTIGATIONBYAPPLYID + param, new JSONObject());
                logger.error("背景调查审批表--" + fileInfo);
                //originResume
                isOrigin = true;
            }
            logger.error("fileInfo--" + fileInfo);
            if (fileInfo == null) {
                throw new BOSException("获取{}文件信息失败: 返回结果为null" + fileType);
            }
            Integer code = fileInfo.getInteger("code");
            if (!Integer.valueOf(200).equals(code)) {
                //未获取到简历不执行
                logger.error("获取{" + fileType + "}文件失败: 返回code={" + code + "}");
                return;
                //throw new BOSException("获取{" + fileType + "}文件失败: 返回code={" + code + "}");
            }
            logger.error("isOrigin--" + isOrigin);
            //背景调查附件单独处理
            if (isOrigin) {
                JSONArray data = fileInfo.getJSONArray("data");
                for (int i = 0; i < data.size(); i++) {
                    JSONObject dataJson = data.getJSONObject(i);
                    //fileDetails-背调报告文件详情列表
                    JSONArray fileDetails = dataJson.getJSONArray("fileDetails");
                    for (int j = 0; j < fileDetails.size(); j++) {
                        JSONObject file = fileDetails.getJSONObject(j);
                        String fileName = file.getString("fileName");
                        String fileExtension = AttachmentUtils.extractFileExtension(fileName);
                        String customFileName = "北森" + (fileType + (j + 1)) + "." + fileExtension;
                        //删除之前的附件
                        String where = "where boid = '" + resumeInfo.getId().toString() + "' and name like '%" + fileName + "%'";
                        logger.error("where--" + where);
                        AttachmentUtils.deleteAttachment(ctx, where);
                        String downloadUrl = file.getString("downloadUrl");
                        // 获取文件内容并保存
                        byte[] fileData = AttachmentUtils.getBytesByNetURL("https:" + downloadUrl);
                        if (fileData == null || fileData.length == 0) {
                            throw new BOSException("获取{" + fileType + "}文件内容失败: 下载内容为空");
                        }
                        AttachmentUtils.insertAttachment(ctx, customFileName, resumeInfo, fileData, fileName);
                    }
                }
            } else {
                JSONObject data = fileInfo.getJSONObject("data");
                if (data == null) {
                    throw new BOSException("获取{" + fileType + "}文件失败: data字段为空");
                }
                String downloadUrl = data.getString("downloadUrl");
                String dfsPath = data.getString("dfsPath");
                if (com.kingdee.bos.rabbitmq.util.StringUtils.isBlank(downloadUrl) || com.kingdee.bos.rabbitmq.util.StringUtils.isBlank(dfsPath)) {
                    throw new BOSException("获取{" + fileType + "}文件失败: downloadUrl或dfsPath为空");
                }
                // 处理文件名
                String fileName = AttachmentUtils.extractFileNameFromPath(dfsPath);
                String fileExtension = AttachmentUtils.extractFileExtension(fileName);
                String customFileName = "北森" + fileType + "." + fileExtension;
                // 获取文件内容并保存
                byte[] fileData = AttachmentUtils.getBytesByNetURL("https:" + downloadUrl);
                if (fileData == null || fileData.length == 0) {
                    throw new BOSException("获取{" + fileType + "}文件内容失败: 下载内容为空");
                }
                AttachmentUtils.insertAttachment(ctx, customFileName, resumeInfo, fileData, fileName);
                logger.error("{" + fileType + "}文件处理成功: {" + customFileName + "}");
            }

            //}
        } catch (Exception e) {
            logger.error("处理" + fileType + "文件时发生异常", e);
        }
    }


    /**
     * 处理简历各部分数据
     */
    private Map processResumeSections(Context ctx, JSONObject resumeJson, ResumeBaseRecInfo resumeInfo) throws BOSException, EASBizException, ParseException, IOException {
        Map mapData = new HashMap();
        JSONArray personProfile = resumeJson.getJSONArray("personProfile");
        saveResumeBaseRec(ctx, personProfile, resumeInfo, mapData);
        JSONArray education = resumeJson.getJSONArray("education");
        saveEducationExpRE(ctx, education, resumeInfo);
        JSONArray workExperience = resumeJson.getJSONArray("workExperience");
        saveWorkingExp(ctx, workExperience, resumeInfo);
        //使用Map定义简历部分与处理方法的对应关系
        Map<String, TriConsumer<Context, JSONArray, ResumeBaseRecInfo>> sectionHandlers = new LinkedHashMap<>();
        //sectionHandlers.put("personProfile", this::saveResumeBaseRec);
        //sectionHandlers.put("workExperience", this::saveWorkingExp);
        //sectionHandlers.put("education", this::saveEducationExpRE);
        sectionHandlers.put("project", this::saveProjectExp);
        sectionHandlers.put("train", this::saveTrainingExp);
        sectionHandlers.put("certificate", this::saveCredential);
        sectionHandlers.put("lang", this::saveLanguageAbility);
        sectionHandlers.put("skill", this::saveProfessionalSkills);
        sectionHandlers.put("awards", this::saveResumeRewardPunish);
        //
        sectionHandlers.put("family", this::saveFamilyInfo);
        // 遍历处理所有简历部分
        sectionHandlers.forEach((sectionKey, handler) -> {
            //判断是否存key
            if (resumeJson.containsKey(sectionKey)) {
                JSONArray sectionData = resumeJson.getJSONArray(sectionKey);
                if (sectionData != null && !sectionData.isEmpty()) {
                    handler.accept(ctx, sectionData, resumeInfo);
                }
            }
        });
        return mapData;
    }

    ///**
    // * 根据申请Id获取标准简历文件
    // *
    // * @param applyId
    // * @return
    // */
    //public JSONObject getStandardResumeFileUrlByApplyId(String applyId) throws IOException {
    //    String param = "?applyId=" + applyId;
    //    BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
    //    JSONObject jsonObject = beisenApiClient.callGetApi(BeisenParam.GET_STANDERDRESUMEFILURLBYAPPLYID + param, new JSONObject());
    //    return jsonObject;
    //}
    //
    ///**
    // * 根据申请Id获取标准简历文件
    // *
    // * @param applyId
    // * @return
    // */
    //public JSONObject getInterviewEvaluationFile(String applyId) throws IOException {
    //    String param = "?applyId=" + applyId;
    //    BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
    //    JSONObject jsonObject = beisenApiClient.callGetApi(BeisenParam.GET_INTERVIEWEVALUATIONFILE + param, new JSONObject());
    //    return jsonObject;
    //}

    /**
     * 根据申请Id获取标准简历
     *
     * @param applyId
     * @return
     */
    public JSONObject getResumeByApplyId(String applyId) throws IOException {
        String param = "?applyId=" + applyId;
        BeisenApiClient beisenApiClient = BeisenApiClient.getInstance();
        JSONObject jsonObject = beisenApiClient.callGetApi(BeisenParam.GET_RESUMEBYAPPLYID + param, new JSONObject());
        return jsonObject;
    }


    /**
     * 招聘管理简历基本信息
     *
     * @param personProfile
     */
    public void saveResumeBaseRec(Context ctx, JSONArray personProfile, ResumeBaseRecInfo resumeBaseRecInfo, Map mapData) throws BOSException, EASBizException, ParseException, IOException {
        logger.error("personProfile--" + personProfile);
        BeisenParamByProperties beisenParamByProperties = new BeisenParamByProperties();
        Map<String, String> config = beisenParamByProperties.getConfig();
        //招聘业务组织
        HROrgUnitInfo hrOrgUnitInfo = new HROrgUnitInfo();
        hrOrgUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
        resumeBaseRecInfo.setHrOrgUnit(hrOrgUnitInfo);
        //来源方式 INTEGRATESYSTEM=集成系统
        resumeBaseRecInfo.setSourceMethod(ResumeSourceMethod.INTEGRATESYSTEM);
        //招聘状态  WAITING 待筛选
        resumeBaseRecInfo.setResumeStatus(ResumeStatusEnum.WAITING);
        //招聘状态  0001 待筛选
        IResumeState iResumeState = ResumeStateFactory.getLocalInstance(ctx);
        ResumeStateInfo resumeStateInfo = iResumeState.getResumeStateInfo("where number = '0001'");
        resumeBaseRecInfo.setResumeState(resumeStateInfo);
        //入库时间
        resumeBaseRecInfo.setWarehouseEntry(new Date());
        //国籍
        INationality iNationality = NationalityFactory.getLocalInstance(ctx);
        //学历
        IDiploma iDiploma = DiplomaFactory.getLocalInstance(ctx);
        //政治面貌
        IPoliticalFace iPoliticalFace = PoliticalFaceFactory.getLocalInstance(ctx);
        //民族
        IFolk iFolk = FolkFactory.getLocalInstance(ctx);
        //婚姻状况
        IWed iWed = WedFactory.getLocalInstance(ctx);
        //血型
        Map<String, String> bloodTypeMap = InitialValueUtils.bloodTypeMap;
        String carType = "";//证件类型
        String carno = "";//证件号
        for (int i = 0; i < personProfile.size(); i++) {
            JSONObject data = personProfile.getJSONObject(i);
            String name = data.getString("name");
            String value = data.getString("value");
            String text = data.getString("text");
            //姓名
            if ("Name".equals(name)) {
                resumeBaseRecInfo.setName(text);
            } else if ("WorkStartTime".equals(name)) {
                //参加工作时间
                resumeBaseRecInfo.setWorkDate(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("YearsOfWork".equals(name) && !com.kingdee.util.StringUtils.isEmpty(text)) {
                //参加工作年限     workSeniority
                resumeBaseRecInfo.setWorkSeniority(text);
            } else if ("YearsOfWork".equals(name) && !com.kingdee.util.StringUtils.isEmpty(text)) {
                //工作年限 YearsOfWork
                resumeBaseRecInfo.setWorkSeniority(text);
            } else if ("CertificateNumber".equals(name)) {
                //身份证号码    identityCardNo
                carno = text;
                if ("身份证".equals(carType)) {
                    resumeBaseRecInfo.setIdentityCardNo(carno);
                    resumeBaseRecInfo.setPassportNo("");
                } else {
                    resumeBaseRecInfo.setPassportNo(carno);
                }
            } else if ("CertificateType".equals(name)) {
                //证件类型
                carType = text;
                if ("身份证".equals(text)) {
                    resumeBaseRecInfo.setIdentityCardNo(carno);
                    resumeBaseRecInfo.setPassportNo("");
                } else {
                    resumeBaseRecInfo.setPassportNo(carno);
                }
            } else if ("Birthday".equals(name)) {
                //出生年月    birthday
                resumeBaseRecInfo.setBirthday(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("AccountArea".equals(name)) {
                //户口所在地    domicilePlace
                resumeBaseRecInfo.setDomicilePlace(text);
            } else if ("QQ".equals(name)) {
                //QQ    QQ
                resumeBaseRecInfo.setQQ(text);
            } else if ("Height".equals(name)) {
                //身高    stature
                resumeBaseRecInfo.setStature(text);
            } else if ("LivingArea".equals(name)) {
                //现居住地    nowResidence
                resumeBaseRecInfo.setNowResidence(text);
            } else if ("Mobile".equals(name)) {
                //手机号    mobilePhone
                resumeBaseRecInfo.setMobilePhone(text);
            } else if ("Telephone".equals(name)) {
                //家庭电话    fixedPhone
                resumeBaseRecInfo.setFixedPhone(text);
            } else if ("Email".equals(name)) {
                //邮件    email
                resumeBaseRecInfo.setEmail(text);
            } else if ("Salary".equals(name)) {
                //目前年薪    annualPay
                resumeBaseRecInfo.setAnnualPay(text);
            } else if ("JobHunting".equals(name)) {
                //目前工作状态    currentWorkingStatus
                resumeBaseRecInfo.setCurrentWorkingStatus(CurrentWorkingStatusEnum.getEnum(Integer.parseInt(value) - 1));
            } else if ("ExpectSalary".equals(name)) {
                //期望年薪    expectantPay
                resumeBaseRecInfo.setExpectantPay(Integer.parseInt(text));
            } else if ("CareerGoals".equals(name)) {
                //职业目标    careerGoal
                resumeBaseRecInfo.setCareerGoal(text);
            } else if ("Evaluation".equals(name)) {
                //自我评价    selfEvaluation
                resumeBaseRecInfo.setSelfEvaluation(text);
            } else if ("Nationality".equals(name)) {
                //国籍    national
                NationalityCollection nationalityCollection = iNationality.getNationalityCollection("where name like '%" + text + "%'");
                if (nationalityCollection.size() > 0) {
                    resumeBaseRecInfo.setNational(nationalityCollection.get(0));
                }
            } else if ("NativeArea".equals(name)) {
                //籍贯  nativePlace
                resumeBaseRecInfo.setNativePlace(text);
            } else if (resumeBaseRecInfo.getBirthday() != null) {
                //年龄  age
                Long yyyy = com.kingdee.util.DateTimeUtils.dateDiff("yyyy", resumeBaseRecInfo.getBirthday(), new Date());
                resumeBaseRecInfo.setAge(yyyy.intValue());
            } else if ("EducationLevel".equals(name)) {
                //最高学历  hDegree
                DiplomaCollection diplomaCollection = iDiploma.getDiplomaCollection("where beisenVal = '" + value + "'");
                if (!diplomaCollection.isEmpty()) {
                    resumeBaseRecInfo.setHDegree(diplomaCollection.get(0));
                }
            } else if ("Polity".equals(name)) {
                //政治面貌  politicalFace
                PoliticalFaceCollection politicalFaceCollection = iPoliticalFace.getPoliticalFaceCollection("where beisenVal = '" + value + "'");
                if (!politicalFaceCollection.isEmpty()) {
                    resumeBaseRecInfo.setPoliticalFace(politicalFaceCollection.get(0));
                }
            } else if (config.get("WedState").equals(name)) {
                //婚姻状况  wed  北森已停用字段
                WedCollection wedCollection = iWed.getWedCollection("where beisenVal = '" + value + "'");
                if (!wedCollection.isEmpty()) {
                    resumeBaseRecInfo.setWed(wedCollection.get(0));
                }
            } else if ("Nation".equals(name)) {
                //民族  folk
                FolkCollection folkCollection = iFolk.getFolkCollection("where beisenVal = '" + value + "'");
                if (!folkCollection.isEmpty()) {
                    resumeBaseRecInfo.setFolk(folkCollection.get(0));
                }
            } else if ("LastSchool".equals(name)) {
                //毕业学校 school
                if (com.kingdee.util.StringUtils.isEmpty(text)) {
                    throw new BOSException("毕业学校不能为空！");
                }
                resumeBaseRecInfo.setName(text);
            } else if ("BloodType".equals(name)) {
                //血型 bloodType
                String hDegree = bloodTypeMap.getOrDefault(value, "90");
                resumeBaseRecInfo.setBloodType(BloodType.getEnum(hDegree));
            } else if ("EmergencyContact".equals(name)) {
                //紧急联系人 emergencyContact
                resumeBaseRecInfo.setEmergencyContact(text);
            } else if ("EmergencyPhone".equals(name)) {
                //紧急联系人电话 emergencyContactPhone
                resumeBaseRecInfo.setEmergencyContactPhone(text);
            } else if ("ExpectSalary".equals(name)) {
                //期望月薪  expectantPayStr
                resumeBaseRecInfo.setExpectantPayStr(text);
            } else if ("LastCompany".equals(name)) {
                //最近工作单位  lastCompany
                resumeBaseRecInfo.setLastCompany(text);
            } else if ("LastIndustry".equals(name)) {
                //最近工作行业  lastIndustry
                resumeBaseRecInfo.setLastIndustry(text);
            } else if ("LastDiscipline".equals(name)) {
                //专业  major
                resumeBaseRecInfo.setMajor(text);
            } else if ("Gender".equals(name)) {
                //性别  gender
                if ("1".equals(value) || "0".equals(value)) {
                    resumeBaseRecInfo.setGender(Genders.getEnum(Integer.parseInt(value) + 1));
                }
            } else if ("ResumeUpdateTime".equals(name)) {
                //更新简历时间  updateResumeDate
                resumeBaseRecInfo.setUpdateResumeDate(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("CertificateGrantUnit".equals(name)) {
                //签发机关  idCardIssueOrg
                resumeBaseRecInfo.setIdentityCardNo(text);
            } else if ("CertificateValidityDate".equals(name)) {
                //证件有效期-开始时间 idCardBeginDate
                resumeBaseRecInfo.setIdCardBeginDate(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("CertificateValidityOverDate".equals(name)) {
                //证件有效期-结束时间 idCardEndDate
                resumeBaseRecInfo.setIdCardEndDate(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("AvailableDate".equals(name)) {
                //到岗时间 arrivalTime
                resumeBaseRecInfo.setArrivalTime(DateTimeUtils.parseDate(text, "yyyy/MM/dd"));
            } else if ("NameEn".equals(name)) {
                //英文名 EnglishName
                resumeBaseRecInfo.setEnglishName(text);
            } else if ("Address".equals(name)) {
                //户籍地址 domicileAddress
                resumeBaseRecInfo.setDomicileAddress(text);
            }
        }
        String errorMsg = "，身份证号码、手机号为必填数据，请在北森维护数据后再次同步！";
        if (com.kingdee.util.StringUtils.isEmpty(resumeBaseRecInfo.getIdentityCardNo()) && com.kingdee.util.StringUtils.isEmpty(resumeBaseRecInfo.getPassportNo())) {
            throw new BOSException("身份证号码不能为空" + errorMsg);
        }
        if (com.kingdee.util.StringUtils.isEmpty(resumeBaseRecInfo.getMobilePhone())) {
            throw new BOSException("手机号码不能为空" + errorMsg);
        }
        IResumeBaseRec iResumeBaseRec = ResumeBaseRecFactory.getLocalInstance(ctx);
        IObjectPK save = iResumeBaseRec.save(resumeBaseRecInfo);
        logger.error("resumeBaseRecId--" + save);
        mapData.put("resumeBaseRecId", save.toString());
        mapData.put("name", resumeBaseRecInfo.getName());
//        } catch (Exception e) {
//            logger.error("简历基本信息报错信息：" + e.getMessage());
//            throw new RuntimeException(e);
//        }
    }

    /**
     * 简历-工作经历
     *
     * @param workExperience
     */
    public void saveWorkingExp(Context ctx, JSONArray workExperience, ResumeBaseRecInfo resumeBaseRecInfo) throws BOSException {
        logger.error("workExperience--" + workExperience);
        try {
            IWorkingExp iWorkingExp = WorkingExpFactory.getLocalInstance(ctx);
            WorkingExpCollection workingExpColl = iWorkingExp.getWorkingExpCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!workingExpColl.isEmpty()) {
                iWorkingExp.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            for (int i = 0; i < workExperience.size(); i++) {
                JSONArray array = workExperience.getJSONArray(i);
                WorkingExpInfo workingExpInfo = new WorkingExpInfo();
                //简历基本信息
                workingExpInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //dateStart	开始时间
                    if ("StartDate".equals(name)) {
                        workingExpInfo.setDateStart(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //dateEnd	结束时间
                    if ("EndDate".equals(name)) {
                        if ("至今".equals(text)) {
                            text = "2199/12";
                        }
                        workingExpInfo.setDateEnd(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //company	公司名称
                    if ("CompanyName".equals(name)) {
                        workingExpInfo.setCompany(text);
                    }
                    //department	任职部门
                    if ("Department".equals(name)) {
                        workingExpInfo.setDepartment(text);
                    }
                    //jobCategory	职位类别
                    if ("OgJobLevel".equals(name)) {
                        workingExpInfo.setJobCategory(text);
                    }
                    //industry	所属行业
                    if ("Industry".equals(name)) {
                        workingExpInfo.setIndustry(text);
                    }
                    //position	职位名称
                    if ("JobTitle".equals(name)) {
                        workingExpInfo.setPosition(text);
                    }
                    //underlingNumber	下属人数
                    if ("SubordinateNumber".equals(name)) {
                        workingExpInfo.setUnderlingNumber(Integer.parseInt(text));
                    }
                    //monthPay	税前月薪
                    if ("Salary".equals(name)) {
                        workingExpInfo.setMonthPay(Integer.parseInt(text));
                    }
                    //certifier	证明人
                    if ("ReferenceName".equals(name)) {
                        workingExpInfo.setCertifier(text);
                    }
                    //leavingReason	离职原因
                    if ("ReasonOfLeaving".equals(name)) {
                        workingExpInfo.setLeavingReason(text);
                    }
                    //certifierPhone	证明人电话
                    if ("ReferenceContact".equals(name)) {
                        workingExpInfo.setCertifierPhone(text);
                    }
                    //monthPayStr	税前月薪
                    if ("Salary".equals(name)) {
                        workingExpInfo.setMonthPayStr(text);
                    }
                    //unitAddress	工作地点  OgJobArea
                    if ("JobArea".equals(name)) {
                        workingExpInfo.setUnitAddress(text);
                    }
                }
                String leavingReason = workingExpInfo.getLeavingReason();
                if (com.kingdee.bos.rabbitmq.util.StringUtils.isEmpty(leavingReason)) {
                    throw new BOSException("工作经历:离职原因不能为空！！");
                }
                iWorkingExp.save(workingExpInfo);

            }
        } catch (Exception e) {
            logger.error("简历-工作经历保存失败！" + e.getMessage());
            throw new BOSException(e);
        }
    }

    /**
     * 简历-教育经历
     *
     * @param education
     */
    public void saveEducationExpRE(Context ctx, JSONArray education, ResumeBaseRecInfo resumeBaseRecInfo) throws BOSException, EASBizException {
        logger.error("education--" + education);
        try {
            IEducationExpREC iEducationExpREC = EducationExpRECFactory.getLocalInstance(ctx);
            EducationExpRECCollection educationExpRECCollection = iEducationExpREC.getEducationExpRECCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!educationExpRECCollection.isEmpty()) {
                iEducationExpREC.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }
            //学历
            IDiploma iDiploma = DiplomaFactory.getLocalInstance(ctx);
            //学位
            IDegree iDegree = DegreeFactory.getLocalInstance(ctx);
            //学院类型
            Map<String, String> bchoolTypeMap = InitialValueUtils.getBchoolTypeMap();
            //最晚开始日期
            Date maxStartDate = null;
            for (int i = 0; i < education.size(); i++) {
                JSONArray array = education.getJSONArray(i);
                EducationExpRECInfo educationExpRECInfo = new EducationExpRECInfo();
                //简历基本信息
                educationExpRECInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //dateStart	开始时间
                    if ("StartDate".equals(name)) {
                        Date date = DateTimeUtils.parseDate(text, "yyyy/MM");
                        educationExpRECInfo.setDateStart(date);
                    }
                    //dateEnd	结束时间
                    if ("EndDate".equals(name)) {
                        if ("至今".equals(text)) {
                            text = "2199/12";
                        }
                        educationExpRECInfo.setDateEnd(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //school	毕业学校
                    if ("SchoolName".equals(name)) {
                        educationExpRECInfo.setSchool(text);
                    }
                    //academicDiplomasF7	学位
                    if ("Degree".equals(name)) {
                        DegreeCollection degreeCollection = iDegree.getDegreeCollection("where beisenVal = '" + value + "'");
                        if (!degreeCollection.isEmpty()) {
                            educationExpRECInfo.setAcademicDiplomasF7(degreeCollection.get(0));
                        }
                    }
                    //major	专业
                    if ("MajorName".equals(name)) {
                        educationExpRECInfo.setMajor(text);
                    }
                    //degreeF7	学历
                    if ("EducationLevel".equals(name)) {
                        DiplomaCollection diplomaCollection = iDiploma.getDiplomaCollection("where beisenVal = '" + value + "'");
                        if (!diplomaCollection.isEmpty()) {
                            educationExpRECInfo.setDegreeF7(diplomaCollection.get(0));
                        }
                    }
                    //schoolType	学院类型
                    if ("SchoolType".equals(name)) {
                        if (bchoolTypeMap.containsKey(value)) {
                            educationExpRECInfo.setSchoolType(SchoolTypeEnum.getEnum(bchoolTypeMap.get(value)));
                        }
                    }
                }
                String errorMsg = "，入学时间、专业、学历、毕业院校为必填数据，请在北森维护数据后再次同步！";
                Date dateStart = educationExpRECInfo.getDateStart();
                if (dateStart == null) {
                    throw new BOSException("教育经历:入学时间不能为空" + errorMsg);
                }
                if (com.kingdee.util.StringUtils.isEmpty(educationExpRECInfo.getMajor())) {
                    throw new BOSException("教育经历:专业不能为空" + errorMsg);
                }
                if (com.kingdee.util.StringUtils.isEmpty(educationExpRECInfo.getSchool())) {
                    throw new BOSException("教育经历:毕业院校不能为空" + errorMsg);
                }
                if (educationExpRECInfo.getDegreeF7() == null) {
                    throw new BOSException("教育经历:学历不能为空" + errorMsg);
                }
                if (maxStartDate == null || maxStartDate.before(dateStart)) {
                    maxStartDate = dateStart;
                    resumeBaseRecInfo.setMajor(educationExpRECInfo.getMajor());
                    resumeBaseRecInfo.setSchool(educationExpRECInfo.getSchool());
                }
                iEducationExpREC.save(educationExpRECInfo);
            }
        } catch (Exception e) {
            IResumeBaseRec iResumeBaseRec = ResumeBaseRecFactory.getLocalInstance(ctx);
            iResumeBaseRec.delete(new ObjectUuidPK(resumeBaseRecInfo.getId()));
            logger.error("简历-教育经历保存失败！" + e.getMessage());
            throw new RuntimeException(e);
        }
        IResumeBaseRec iResumeBaseRec = ResumeBaseRecFactory.getLocalInstance(ctx);
        iResumeBaseRec.save(resumeBaseRecInfo);
    }

    /**
     * 简历-获奖经历
     *
     * @param awards
     */
    public void saveResumeRewardPunish(Context ctx, JSONArray awards, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("awards--" + awards);
        try {
            IResumeRewardPunish iResumeRewardPunish = ResumeRewardPunishFactory.getLocalInstance(ctx);
            ResumeRewardPunishCollection ResumeRewardPunishCollection = iResumeRewardPunish.getResumeRewardPunishCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!ResumeRewardPunishCollection.isEmpty()) {
                iResumeRewardPunish.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            for (int i = 0; i < awards.size(); i++) {
                JSONArray array = awards.getJSONArray(i);
                ResumeRewardPunishInfo ResumeRewardPunishInfo = new ResumeRewardPunishInfo();
                //简历基本信息
                ResumeRewardPunishInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //occurDate	获奖时间
                    if ("AwardTime".equals(name)) {
                        ResumeRewardPunishInfo.setOccurDate(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //title	获奖名称
                    if ("AwardName".equals(name)) {
                        ResumeRewardPunishInfo.setTitle(text);
                        ResumeRewardPunishInfo.setName(text);
                    }
                    //description	描述
                    if ("AwardDescription".equals(name)) {
                        ResumeRewardPunishInfo.setDescription(text);
                    }
                }
                iResumeRewardPunish.save(ResumeRewardPunishInfo);

            }
        } catch (Exception e) {
            logger.error("简历-获奖经历保存失败！" + e.getMessage());
        }

    }

    /**
     * 简历-项目经历
     *
     * @param project
     */
    public void saveProjectExp(Context ctx, JSONArray project, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("project--" + project);
        try {
            IProjectExp iProjectExp = ProjectExpFactory.getLocalInstance(ctx);
            ProjectExpCollection ProjectExpCollection = iProjectExp.getProjectExpCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!ProjectExpCollection.isEmpty()) {
                iProjectExp.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            for (int i = 0; i < project.size(); i++) {
                JSONArray array = project.getJSONArray(i);
                ProjectExpInfo ProjectExpInfo = new ProjectExpInfo();
                //简历基本信息
                ProjectExpInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {

                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //dateStart	开始时间
                    if ("StartDate".equals(name)) {
                        ProjectExpInfo.setDateStart(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //dateEnd	结束时间
                    if ("EndDate".equals(name)) {
                        if ("至今".equals(text)) {
                            text = "2199/12";
                        }
                        ProjectExpInfo.setDateEnd(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //customer	项目名称
                    if ("ProjectName".equals(name)) {
                        ProjectExpInfo.setCustomer(text);
                    }
                    //projectDescription	项目描述
                    if ("ProjectInfo".equals(name)) {
                        ProjectExpInfo.setProjectDescription(text);
                    }
                }
                iProjectExp.save(ProjectExpInfo);

            }
        } catch (Exception e) {
            logger.error("简历-项目经历保存失败！" + e.getMessage());
        }

    }

    /**
     * 简历-培训经历
     *
     * @param train
     */
    public void saveTrainingExp(Context ctx, JSONArray train, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("train--" + train);
        try {
            ITrainingExp iTrainingExp = TrainingExpFactory.getLocalInstance(ctx);
            TrainingExpCollection TrainingExpCollection = iTrainingExp.getTrainingExpCollection("where resumeBaseInfo = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!TrainingExpCollection.isEmpty()) {
                iTrainingExp.delete("where resumeBaseInfo = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            for (int i = 0; i < train.size(); i++) {
                JSONArray array = train.getJSONArray(i);
                TrainingExpInfo TrainingExpInfo = new TrainingExpInfo();
                //简历基本信息
                TrainingExpInfo.setResumeBaseInfo(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //dateStart	开始时间
                    if ("StartDate".equals(name)) {
                        TrainingExpInfo.setDateStart(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //dateEnd	结束时间
                    if ("EndDate".equals(name)) {
                        if ("至今".equals(text)) {
                            text = "2199/12";
                        }
                        TrainingExpInfo.setDateEnd(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //trainingInstitution	培训机构
                    if ("OrgName".equals(name)) {
                        TrainingExpInfo.setTrainingInstitution(text);
                    }
                    //courseDescription	课程描述
                    if ("Description".equals(name)) {
                        TrainingExpInfo.setCourseDescription(text);
                    }
                }
                iTrainingExp.save(TrainingExpInfo);

            }
        } catch (Exception e) {
            logger.error("简历-培训经历保存失败！" + e.getMessage());
        }


    }

    /**
     * 简历-获得证书
     *
     * @param certificate
     */
    public void saveCredential(Context ctx, JSONArray certificate, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("certificate--" + certificate);

        try {
            ICredential iCredential = CredentialFactory.getLocalInstance(ctx);
            CredentialCollection CredentialCollection = iCredential.getCredentialCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!CredentialCollection.isEmpty()) {
                iCredential.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            for (int i = 0; i < certificate.size(); i++) {
                JSONArray array = certificate.getJSONArray(i);
                CredentialInfo credentialInfo = new CredentialInfo();
                //简历基本信息
                credentialInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);

                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //date	证书发放日期
                    if ("ObtainDate".equals(name)) {
                        credentialInfo.setDate(DateTimeUtils.parseDate(text, "yyyy/MM"));
                    }
                    //credentialName	证书名称
                    if ("CertificateName".equals(name)) {
                        credentialInfo.setCredentialName(text);
                    }
                    //issuer	证书发布机构
                    if ("Authority".equals(name)) {
                        credentialInfo.setIssuer(text);
                    }
                    //grade	证书成绩
                    if ("Score".equals(name)) {
                        credentialInfo.setGrade(text);
                    }
                }
                iCredential.save(credentialInfo);

            }
        } catch (Exception e) {
            logger.error("简历-获得证书保存失败！" + e.getMessage());
        }

    }

    /**
     * 简历-语言能力
     *
     * @param lang
     */
    public void saveLanguageAbility(Context ctx, JSONArray lang, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("lang--" + lang);
        try {
            ILanguageAbility iLanguageAbility = LanguageAbilityFactory.getLocalInstance(ctx);
            LanguageAbilityCollection LanguageAbilityCollection = iLanguageAbility.getLanguageAbilityCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!LanguageAbilityCollection.isEmpty()) {
                iLanguageAbility.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }

            //熟练度
            Map<String, String> proficiencyMap = InitialValueUtils.getProficiencyMap();
            for (int i = 0; i < lang.size(); i++) {
                JSONArray array = lang.getJSONArray(i);
                LanguageAbilityInfo languageAbilityInfo = new LanguageAbilityInfo();
                //简历基本信息
                languageAbilityInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //listeningSpeaking	听说
                    if ("ListeningSpeakingAbility".equals(name)) {
                        if (proficiencyMap.containsKey(value)) {
                            languageAbilityInfo.setListeningSpeaking(ProficiencyEnum.getEnum(proficiencyMap.get(value)));
                        }
                    }
                    //readingWriting	读写
                    if ("ReadingWritingAbility".equals(name)) {
                        languageAbilityInfo.setReadingWriting(ProficiencyEnum.getEnum(proficiencyMap.get(value)));
                    }
                    //language	语言
                    if ("LanguageType".equals(name)) {
                        languageAbilityInfo.setLanguage(text);
                    }
                    //lv	语言等级
                    if ("LanguageLevel".equals(name)) {
                        languageAbilityInfo.setLv(text);
                    }
                }
                iLanguageAbility.save(languageAbilityInfo);

            }
        } catch (Exception e) {
            logger.error("简历-语言能力保存失败！" + e.getMessage());
        }
    }

    /**
     * 简历-专业技能
     *
     * @param skill
     */
    public void saveProfessionalSkills(Context ctx, JSONArray skill, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("skill--" + skill);
        try {
            IProfessionalSkills iProfessionalSkills = ProfessionalSkillsFactory.getLocalInstance(ctx);
            ProfessionalSkillsCollection ProfessionalSkillsCollection = iProfessionalSkills.getProfessionalSkillsCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            if (!ProfessionalSkillsCollection.isEmpty()) {
                iProfessionalSkills.delete("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            }
            for (int i = 0; i < skill.size(); i++) {
                JSONArray array = skill.getJSONArray(i);
                ProfessionalSkillsInfo professionalSkillsInfo = new ProfessionalSkillsInfo();
                //简历基本信息
                professionalSkillsInfo.setResumeBase(resumeBaseRecInfo);
                for (int j = 0; j < array.size(); j++) {

                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //skillName	技能名称
                    if ("SkillName".equals(name)) {
                        professionalSkillsInfo.setSkillName(text);
                    }
                    //skillDescription	技能描述
                    if ("SkillDescription".equals(name)) {
                        professionalSkillsInfo.setSkillDescription(text);
                    }
                }
                iProfessionalSkills.save(professionalSkillsInfo);

            }
        } catch (Exception e) {
            logger.error("简历-专业技能保存失败！" + e.getMessage());
        }
    }

    /**
     * 简历-社会关系
     *
     * @param
     */
    public void saveFamilyInfo(Context ctx, JSONArray family, ResumeBaseRecInfo resumeBaseRecInfo) {
        logger.error("family--" + family);
        try {
            IResumeFamily familyIns = ResumeFamilyFactory.getLocalInstance(ctx);
            ResumeFamilyCollection familyCol = familyIns.getResumeFamilyCollection("where resumeBase = '" + resumeBaseRecInfo.getId().toString() + "'");
            //关系
            IRelation relationIns = RelationFactory.getLocalInstance(ctx);
            //简历基本信息
            for (int i = 0; i < family.size(); i++) {
                ResumeFamilyInfo familyInfo = new ResumeFamilyInfo();
                if (familyCol.size() > i) {
                    familyInfo = familyCol.get(i);
                }
                familyInfo.setResumeBase(resumeBaseRecInfo);

                JSONArray array = family.getJSONArray(i);
                for (int j = 0; j < array.size(); j++) {
                    JSONObject data = array.getJSONObject(j);
                    String name = data.getString("name");
                    String value = data.getString("value");
                    String text = data.getString("text");
                    //姓名
                    if ("Name".equals(name)) {
                        familyInfo.setName(value);
                    }
                    // 与本人关系
                    if ("relation".equals(name)) {
                        RelationCollection relationCol = relationIns.getRelationCollection("where beisenVal = '" + value + "'");
                        if (!relationCol.isEmpty()) {
                            familyInfo.setRelation(relationCol.get(0));
                        }
                    }
                    if ("age".equals(name)) {
                        familyInfo.setAge(text);
                    }
                    //职务
                    if ("JobTitle".equals(name)) {
                        familyInfo.setSpecDuty(text);
                    }
                    //公司名
                    if ("CompanyName".equals(name)) {
                        familyInfo.setWorkUnit(text);
                    }
                    //telephone
                    if ("telephone".equals(name)) {
                        familyInfo.setOfficePhone(text);
                    }
                    familyIns.save(familyInfo);
                }
            }
        } catch (Exception e) {
            logger.error("社会关系保存失败！" + e.getMessage());
            throw new RuntimeException(e);
        }
    }


    /**
     * coyle
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _syncRecuritmentToBeisen(Context ctx, String billId) throws BOSException, EASBizException {
        super._syncRecuritmentToBeisen(ctx, billId);
        IRecuritmentDemand dIns = RecuritmentDemandFactory.getLocalInstance(ctx);
        RecuritmentDemandInfo recuritmentDemandInfo = dIns.getRecuritmentDemandInfo(new ObjectUuidPK(billId));
        //更新或新增
        try {
            //测试环境或者线上环境
            boolean isProductionEnv = false;
            BeisenParamByProperties beisenParamByProperties = new BeisenParamByProperties();
            Map<String, String> config = beisenParamByProperties.getConfig();
            String isProductionEnvStr = config.get("isProductionEnv");// 线上环境
            if (!StringUtils.isEmpty(isProductionEnvStr) && isProductionEnvStr.equals("true")) {
                isProductionEnv = true;
            }
            RecruitmentDemandService recruitmentDemandService = new RecruitmentDemandService(isProductionEnv);
            Object requirementId = recuritmentDemandInfo.get("requirementId");
            if (ObjectUtils.allNotNull(requirementId)) {
                recruitmentDemandService.updateRequirement(ctx, String.valueOf(requirementId), recuritmentDemandInfo);
            } else {
                recruitmentDemandService.createRecruitmentDemand(ctx, recuritmentDemandInfo);
            }
        } catch (Exception e) {
            SelectorItemCollection selectorCol = new SelectorItemCollection();
            selectorCol.add(new SelectorItemInfo("syncBeisenResult"));
            String message = e.getMessage();
            recuritmentDemandInfo.put("syncBeisenResult", "失败: " + message);
            dIns.updatePartial(recuritmentDemandInfo, selectorCol);
            throw new RuntimeException(e);
        }
    }


    /**
     * 招聘需求更新
     * coyle
     */
    @Override
    protected void _updateRecuritment(Context ctx, String startDate, String endDate, int offset) throws BOSException, EASBizException {
        super._updateRecuritment(ctx, startDate, endDate, offset);

        // 0. 参数校验与日期解析
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate start = LocalDate.now();
        LocalDate end = LocalDate.now();
        //如果时间参数都为空,则使用offset参数
        if (StringUtils.isEmpty(startDate) && StringUtils.isEmpty(endDate)) {
            if (offset > 0) {
                //eDate增加offset天
                end = end.plusDays(offset);
            } else if (offset < 0) {
                start = start.plusDays(offset);
            }
        }
        if (!StringUtils.isEmpty(startDate)) {
            //开始日期字定义,结束日期都是今天
            start = LocalDate.parse(startDate, dateFormatter);
        }
        if (!StringUtils.isEmpty(endDate)) {
            //开始日期,结束日期都是今天
            end = LocalDate.parse(endDate, dateFormatter);
        }
        if (start.isAfter(end)) {
            throw new BOSException("开始日期不能晚于结束日期");
        }

        // LocalDate 转 String (使用之前的 dateFormatter)
        String startStr = toStartTime(start.format(dateFormatter));
        String endStr = toEndTime(end.format(dateFormatter));

        IRecuritmentDemand localInstance = RecuritmentDemandFactory.getLocalInstance(ctx);
        EntityViewInfo ev = new EntityViewInfo();
        FilterInfo filter = new FilterInfo();
        filter.getFilterItems().add(new FilterItemInfo("requirementId", null, CompareType.NOTEMPTY));
        filter.getFilterItems().add(new FilterItemInfo("lastUpdateTime", startStr, CompareType.GREATER_EQUALS));
        filter.getFilterItems().add(new FilterItemInfo("lastUpdateTime", endStr, CompareType.LESS_EQUALS));
        ev.setFilter(filter);

        RecuritmentDemandCollection recuritmentDemandCollection = localInstance.getRecuritmentDemandCollection(ev);
        for (int i = 0; i < recuritmentDemandCollection.size(); i++) {
            RecuritmentDemandInfo recuritmentDemandInfo = recuritmentDemandCollection.get(i);
            _syncRecuritmentToBeisen(ctx, recuritmentDemandInfo.getId().toString());
        }

    }


    /**
     * 将日期字符串转换为一天的开始时间（UTC格式）
     *
     * @param dateStr "yyyy-MM-dd"格式的日期字符串
     * @return Moka API要求的时间格式
     */
    public static String toStartTime(String dateStr) {
        LocalDate date = LocalDate.parse(dateStr);
        LocalDateTime startOfDay = date.atStartOfDay();
        return TIME_FORMATTER.format(startOfDay);
    }

    /**
     * 将日期字符串转换为一天的结束时间（UTC格式）
     *
     * @param dateStr "yyyy-MM-dd"格式的日期字符串
     * @return Moka API要求的时间格式
     */
    public static String toEndTime(String dateStr) {
        LocalDate date = LocalDate.parse(dateStr);
        LocalDateTime endOfDay = date.atTime(23, 59, 59);
        return TIME_FORMATTER.format(endOfDay);
    }


}
