package com.yonyou.hrcloud.attentrpt.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.yonyou.hrcloud.adder.context.AppContext;
import com.yonyou.hrcloud.adder.exception.AdderBusinessException;
import com.yonyou.hrcloud.adder.helper.IDHelper;
import com.yonyou.hrcloud.adder.model.param.PagerRequest;
import com.yonyou.hrcloud.adder.model.param.Sorter;
import com.yonyou.hrcloud.adder.model.query.ChainLogicExpression;
import com.yonyou.hrcloud.adder.model.query.Condition;
import com.yonyou.hrcloud.adder.model.query.Operator;
import com.yonyou.hrcloud.adder.model.query.ValueExpression;
import com.yonyou.hrcloud.adder.service.IGenericService;
import com.yonyou.hrcloud.attend.helper.MultilingualTranslateHelper;
import com.yonyou.hrcloud.attend.model.AttendSchemeVO;
import com.yonyou.hrcloud.attend.model.AttendStaff;
import com.yonyou.hrcloud.attend.service.IAttendSchemeService;
import com.yonyou.hrcloud.attend.service.IAttendStaffService;
import com.yonyou.hrcloud.attentrpt.dao.IAttendRptCalDao;
import com.yonyou.hrcloud.attentrpt.dao.IAttendRptDao;
import com.yonyou.hrcloud.attentrpt.helper.utils.TsAttendRptUtils;
import com.yonyou.hrcloud.attentrpt.model.*;
import com.yonyou.hrcloud.attentrpt.service.ITsAttendRptAsyncService;
import com.yonyou.hrcloud.attentrpt.service.ITsAttendRptService;
import com.yonyou.hrcloud.attentrpt.service.ITsAttentRptDayCalService;
import com.yonyou.hrcloud.attentrpt.service.ITsAttentRptMonCalService;
import com.yonyou.hrcloud.attentrpt.util.ExcelConstant;
import com.yonyou.hrcloud.attentrpt.util.PoiUtil;
import com.yonyou.hrcloud.berry.helper.DateStyle;
import com.yonyou.hrcloud.berry.helper.DateUtil;
import com.yonyou.hrcloud.businesstrip.service.IBusinessTripTypeService;
import com.yonyou.hrcloud.calendar.helper.CalendarCommon;
import com.yonyou.hrcloud.commons.org.model.CommonOrg;
import com.yonyou.hrcloud.commons.staff.model.CommonSimpleStaff;
import com.yonyou.hrcloud.commons.staff.model.CommonStaffJob;
import com.yonyou.hrcloud.formula.helper.FormulaUtils;
import com.yonyou.hrcloud.lang.helper.LangHelper;
import com.yonyou.hrcloud.leave.service.ILeaveTypeNewService;
import com.yonyou.hrcloud.ncc.helper.InSQLCreator;
import com.yonyou.hrcloud.tcommon.helper.IServceCodeConstant;
import com.yonyou.hrcloud.tcommon.helper.staffAndOrg.OrgCommonHepler;
import com.yonyou.hrcloud.tcommon.helper.staffAndOrg.SimpleStaffCommonHepler;
import com.yonyou.hrcloud.tcommon.helper.staffAndOrg.SqlQueryHpler;
import com.yonyou.hrcloud.tcommon.model.NCCAsyncParam;
import com.yonyou.hrcloud.tcommon.model.StaffInfo;
import com.yonyou.hrcloud.tcommon.model.TimeConst;
import com.yonyou.hrcloud.tcommon.service.IStaffAttendCommonService;
import com.yonyou.hrcloud.tcommon.service.ItimeCommonService;
import com.yonyou.hrcloud.tcommon.utils.MultiLangHelper;
import com.yonyou.hrcloud.tcommon.utils.MySortListUtils;
import com.yonyou.hrcloud.tcommon.utils.StrConversionUtils;
import com.yonyou.hrcloud.tcommon.utils.TranslatorToMapUtils;
import com.yonyou.hrcloud.timeitem.helper.ITsFormulaConstant;
import com.yonyou.hrcloud.timeitem.model.TimeItemVO;
import com.yonyou.hrcloud.timeitem.service.ITimeItemService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by wenbinc on 2017/9/5.
 */
@Slf4j
@Service
@Transactional
public class TsAttendRptServiceImpl implements ITsAttendRptService {

    @Autowired
    IAttendRptDao attendRptdao;
    @Autowired
    IAttendStaffService attendStaffService;
    @Resource
    private ITimeItemService itemService;
    @Lazy
    @Resource
    private ITsAttentRptDayCalService tsAttentRptDayCalServiceImpl;
    @Lazy
    @Resource
    ITsAttentRptMonCalService tsAttentRptMonCalService;
    @Autowired
    private IGenericService genericService;
    @Autowired
    private IAttendSchemeService attendSchemeService;
    @Autowired
    private IStaffAttendCommonService staffAttendCommonService;
    @Autowired
    private IAttendSchemeService iAttendSchemeService;
    @Resource
    private IAttendRptCalDao attendRptCalDao;
    @Resource
    private ItimeCommonService itimeCommonService;
    @Resource
    private ILeaveTypeNewService leaveTypeService;
    @Resource
    private IBusinessTripTypeService tripTypeService;
    @Autowired
    private SimpleStaffCommonHepler simpleStaffCommonHepler;
    @Autowired
    private OrgCommonHepler orgCommonHepler;
    public String attendSchemeVOName;
    @Autowired
    private ITsAttendRptAsyncService attendRptAsyncService;

    private Gson gson;
    /**
     * 获取考勤日月报的栏目信息
     *
     * @param reportType 0：日报，1：月报
     * @return
     */
    @Override
    public Object queryItemViewData(String schemeId, Integer reportType) {
        //AttendSchemeVO attendSchemeVO=getAttendSchemeVO(schemeId,true);
        AttendSchemeVO attendSchemeVO = genericService.load(AttendSchemeVO.class, schemeId);
        //Map<String, Object> map = queryVieworderMap(attendSchemeVO.getItemSchemeId(),attendSchemeVO.getLeaveRuleId(),report_type);
        return queryViewOrderMapByScheme(attendSchemeVO, reportType);
    }

    @Override
    /**
     * 考勤日报删除根据user_id
     * @return
     */
    public void batchDelRptBByPid(Condition con) {
        attendRptdao.batchViewDelRptBByPid(con);
    }

    @Override
    /**
     * 考勤日报显示列表批量插入
     * @return
     */
    public void batchViewRptVOs(List<AttendVieworderRptVO> list) {
        genericService.insertByBatch(list);
    }

    /**
     * Web端日月报查询栏目设置
     *
     * @return
     */
    private Map<String, Object> queryVieworderMap(String itemMainId, String leaveRuleId, Integer reportType) {
        if (StringUtils.isBlank(itemMainId)) {
            throw new AdderBusinessException("该考勤方案没有相应的考勤项目方案", "attend.report.i18n12");
        }
        //1 获取日报考勤项目:如果显示列表中数据为空，则取考勤项目中的启用状态的 获取考勤项目中的所有日报项目
        List<TimeItemVO> itemVOList = itemService.queryTimeItemsExt(itemMainId, leaveRuleId, String.valueOf(reportType), true, null);
        return getViewOrderMap(itemMainId, reportType, itemVOList);
    }

    /**
     * Web端日月报查询栏目设置
     *
     * @return
     */
    private Map<String, Object> queryViewOrderMapByScheme(AttendSchemeVO attendSchemeVO, Integer reportType) {
        if (StringUtils.isBlank(attendSchemeVO.getItemSchemeId())) {
            throw new AdderBusinessException("该考勤方案没有相应的考勤项目方案", "attend.report.i18n12");
        }
        //1 获取日报考勤项目:如果显示列表中数据为空，则取考勤项目中的启用状态的 获取考勤项目中的所有日报项目
        List<TimeItemVO> itemVOList = itemService.queryTimeItemsExtBySchema(attendSchemeVO, String.valueOf(reportType), true, null);
        return getViewOrderMap(attendSchemeVO.getItemSchemeId(), reportType, itemVOList);
    }

    private Map<String, Object> getViewOrderMap(String mainId, Integer reportType, List<TimeItemVO> itemVOList) {
        Map<String, Object> map = new HashMap<>();
        //获取日报的显示列表
        Condition vcond = new Condition();
        String userid = AppContext.getContext().getUserId();
        vcond.addExpression("itemmain_id", mainId);
        vcond.addExpression("report_type", reportType);
        Sort sort = new Sorter(Sort.Direction.ASC, "displayorder");
        List<AttendVieworderRptVO> viewlist = attendRptdao.queryVieworderList(vcond, sort);
        Map<String, AttendVieworderRptVO> viewlistMap = queryviewVOListMap(viewlist);
        //获取显示列表和非显示列表
        List<AttendVieworderRptVO> showOrderList = new ArrayList<>();
        List<AttendVieworderRptVO> unShowOrderList = new ArrayList<>();
        AttendVieworderRptVO viewNew;
        int viewShowCount = 0;
        int viewUnShowCount = 0;
        boolean isfirst = true;
        if (viewlistMap.size() > 0) {
            isfirst = false;
        }
        int len = itemVOList.size();
        for (TimeItemVO tiemVo : itemVOList) {
            if (viewlistMap.containsKey(tiemVo.getId())) {
                viewNew = viewlistMap.get(tiemVo.getId());
            } else {
                viewNew = new AttendVieworderRptVO();
                viewNew.setId((String) IDHelper.nextId());
                viewNew.setPkTimeitem(tiemVo.getId());
                viewNew.setShowFlag(tiemVo.getShowFlag() != null ? tiemVo.getShowFlag() : false);
                if (!isfirst) {
                    if (tiemVo.getShoworder() != null)
                        viewNew.setDisplayorder(tiemVo.getShoworder() + len);
                }
                viewNew.setItemSource(0);
            }
            if (tiemVo.getSource() == null || 1 == tiemVo.getSource()) {
                viewNew.setItemSource(0);
            } else {
                viewNew.setItemSource(1);
            }
            viewNew.setReportType(reportType);
            viewNew.setUserId(userid);
            viewNew.setItemmainId(mainId);
            //设置多语名称
            viewNew.setItemname(MultiLangHelper.getLangName(tiemVo, "name"));
            viewNew.setItemcode(tiemVo.getCode());
            viewNew.setItemdatacode(tiemVo.getDbcode());
            viewNew.setIfromflag(tiemVo.getIfromflag());
            viewNew.setIfldwidth(tiemVo.getIfldwidth());
            viewNew.setIflddecimal(tiemVo.getIflddecimal());
            viewNew.setIdatatype(tiemVo.getIdatatype());
            viewNew.setIdatatypeName(tiemVo.getIdatatypeName());
            viewNew.setTrunType(tiemVo.getTrunType());
            if (viewNew.getShowFlag()) {
                if (isfirst) {
                    viewShowCount++;
                    viewNew.setDisplayorder(viewShowCount);
                }
                showOrderList.add(viewNew);
            } else {
                if (isfirst) {
                    viewUnShowCount++;
                    viewNew.setDisplayorder(viewUnShowCount);
                }
                unShowOrderList.add(viewNew);
            }
        }
        //排序
        MySortListUtils<AttendVieworderRptVO> msList = new MySortListUtils<>();
        msList.sortByMethod(showOrderList, "getDisplayorder", false);

        map.put("showorderlist", showOrderList);
        map.put("unshoworderlist", unShowOrderList);
        return map;
    }

    private Map<String, AttendVieworderRptVO> queryviewVOListMap(List<AttendVieworderRptVO> viewVOList) {
        return viewVOList.stream().collect(Collectors.toMap(AttendVieworderRptVO::getPkTimeitem, a -> a, (k1, k2) -> k1));
    }
    //endregion
    //region 日月报查询

    /**
     * Web端日月报查询共有方法
     *
     * @param reportType 0：日报 1：月报
     * @param qcond
     * @param pageable
     * @return
     */
    @Override
    public Object dealDayAndMonthCommon(String schemeId, Integer reportType, String staffName, String deptId, boolean isIncludeSub, Condition qcond, Pageable pageable) {
        return dealDayAndMonthCommon(schemeId, reportType, staffName, deptId, isIncludeSub, qcond, pageable, true);
    }

    @Override
    public Object dealDayAndMonthCommon(String schemeId, Integer reportType, String staffName, String deptId, boolean isIncludeSub, Condition qcond, Pageable pageable, boolean isPower) {
        //2.2 获得设置的列表数据
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("######## dealDayAndMonthCommon getAttendSchemeVOWeb");
        AttendSchemeVO attendSchemeVO = getAttendSchemeVOWeb(schemeId, deptId, isIncludeSub, isPower);
        stopWatch.stop();
        if (attendSchemeVO == null) {
            throw new AdderBusinessException("没有对应的假勤方案！", "attend.report.i18n59");
        }
        this.attendSchemeVOName = MultiLangHelper.getLangName(attendSchemeVO, "name");
        stopWatch.start("######## dealDayAndMonthCommon queryVieworderMapByScheme");
        Map<String, Object> data = queryViewOrderMapByScheme(attendSchemeVO, reportType);
        List<AttendVieworderRptVO> showOrderList = new ArrayList<>();
        if (data != null) {
            showOrderList = (List<AttendVieworderRptVO>) data.get("showorderlist");
        }
        if (showOrderList.size() == 0) {
            log.error("请至少选择一个栏目！");
            throw new AdderBusinessException("请至少选择一个栏目！", "attend.report.i18n46");
        }
        stopWatch.stop();
        stopWatch.start("######## dealDayAndMonthCommon getTitleData");
        Map<String, Object> titleresult = getTitleData(reportType, showOrderList);
        String columns = String.valueOf(titleresult.get("columns"));
        stopWatch.stop();
        stopWatch.start("######## dealDayAndMonthCommon deal");
        //主表数据
        Object qdata = null;
        if (CollectionUtils.isNotEmpty(attendSchemeVO.getOrgs())) {
            qcond = getDeptAndChildIds(attendSchemeVO.getOrgs(), staffName, qcond, reportType, isIncludeSub);
            if (reportType == 0) {
                qdata = dealDay(qcond, pageable, columns);
            } else {
                qdata = dealMonth(qcond, pageable, columns);
            }
        }
        Map<String, Object> resultdata = new HashMap<>();
        resultdata.put("title", titleresult.get("titleList"));
        resultdata.put("data", qdata);
        resultdata.put("itemdata", titleresult.get("itemJson"));
        stopWatch.stop();
        log.debug(stopWatch.prettyPrint());
        return resultdata;
    }

    /**
     * 获取日月包总数
     */
    private Map<String, Object> getDayAndMonthTotalNum(int report_type, AttendSchemeVO attendSchemeVO, AttendRptIInfoVO attendRptIInfoVO) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
//    	Pageable pageable = new PageRequest(0, 999999);
        if (attendSchemeVO.getOrgs() != null && attendSchemeVO.getOrgs().size() > 0) {
            String staffName = attendRptIInfoVO.getStaffname();
            Condition qcond = attendRptIInfoVO.getCon();
//            qcond = getDeptIdsPowerCondNew(attendSchemeVO.getOrgs(),staffName,qcond);
            if (report_type == 0) {
                qcond = getDeptIdsPowerCondNew(attendSchemeVO.getOrgs(), staffName, qcond, attendRptIInfoVO.isIncludeSub());
//            	resultMap.put("dayRptNum", getDealDayNum(qcond, pageable));
                resultMap.put("dayRptNum", getDealDayNum(qcond));
            } else {
                List<String> deptid_select = orgCommonHepler.getOrgAndChildIds(attendSchemeVO.getOrgs(), "2", attendRptIInfoVO.isIncludeSub());
                qcond.addExpression("dept_id", deptid_select, "in");
                List<AttendStaff> attendStaffList = queryAttendStaff(attendRptIInfoVO.getJobId(), staffName);
                //如果有职务或人员信息，先根据职务和人员姓名查找人员数据，再查询月报数据，最后翻译
                if (CollectionUtils.isNotEmpty(attendStaffList)) {
                    List<String> idList = com.yonyou.hrcloud.tcommon.utils.FormulaUtils.getPropertyListFromBeanVO(attendStaffList, "staffId");
                    qcond.addExpression("staff_id", idList, Operator.IN);
                }
//            	resultMap.put("monthRptNum", getDealMonthNum(qcond, pageable));
                resultMap.put("monthRptNum", getDealMonthNum(qcond));
            }
        }
        return resultMap;
    }

    //获取日报总数
//    private int getDealDayNum(Condition qcond, Pageable pageable) {
    private int getDealDayNum(Condition qcond) {
        int resultNum = attendRptdao.queryTsdayStatNum(qcond);
        return resultNum;
    }

    //获取月报总数
//    private int getDealMonthNum(Condition qcond, Pageable pageable) {
    private int getDealMonthNum(Condition qcond) {
        int resultNum = attendRptdao.queryTsMonthStatNum(qcond);
        return resultNum;
    }

    private Map<String, Object> getTitleData(Integer reportType, List<AttendVieworderRptVO> showOrderList) {
        Map<String, Object> titleResult = new HashMap<>();

        JSONArray itemEditJsonArray = new JSONArray();
        JSONArray titleListJsonArray = gettitleresult(reportType);
        //2.2 获得设置的列表数据
        //2.2.1 拼凑查询code
        StringBuilder sbItemCode = new StringBuilder();
        int titleJsonArrayLen = titleListJsonArray.size();
        String tableAlias = reportType == 0 ? "day." : "month.";
        for (AttendVieworderRptVO view : showOrderList) {
            if (view.getItemdatacode() != null) {
                if (view.getItemSource() == 0) {
                    sbItemCode.append(",").append(tableAlias).append(view.getItemdatacode());
                    titleListJsonArray.add(titleJsonArrayLen, addJosn(view.getItemdatacode(), view.getItemname(), view.getIdatatype(), view.getDisplayorder(), titleJsonArrayLen, view.getIflddecimal()));
                    titleJsonArrayLen++;
                }
                if ("1".equals(view.getIfromflag())) {
                    JSONObject itemJson = new JSONObject();
                    itemJson.put("key", StrConversionUtils.lineToHump(view.getItemdatacode()));
                    itemJson.put("columnkey", view.getItemdatacode());
                    itemJson.put("name", view.getItemname());
                    itemJson.put("type", view.getIdatatype());
                    itemJson.put("ifldwidth", view.getIfldwidth());
                    itemJson.put("iflddecimal", view.getIflddecimal());
                    itemJson.put("idatatypeName", view.getIdatatypeName());
                    itemJson.put("trunType", view.getTrunType());
                    itemEditJsonArray.add(itemJson);
                }
            } else {
                if (view.getItemSource() == 1) {
                    titleListJsonArray.add(titleJsonArrayLen, addJosn(view.getPkTimeitem(), view.getItemname(), view.getIdatatype(), view.getDisplayorder(), titleJsonArrayLen, view.getIflddecimal()));
                    titleJsonArrayLen++;
                }
            }
        }
        //3.根据code和获取数据（主表和子表）
        String columns = sbItemCode.toString();
        titleResult.put("columns", columns);
        titleResult.put("titleList", titleListJsonArray);
        titleResult.put("itemJson", itemEditJsonArray);
        return titleResult;
    }

    //日报处理
    //source 0:非导出 1:导出
    private Object dealDay(Condition qcond, Pageable pageable, String columns) {
        log.debug("获取主表数据 start");
        Page<AttendDayRptVO> attendDayRptVOPages = getAttenddayRptByNew(qcond, pageable, columns);
        log.debug("获取主表数据 end");
        if (attendDayRptVOPages != null) {
            List<String> pkAttendRpt = new ArrayList<>();
            // 部门id
            List<String> listDeptIds = new ArrayList<>();
            // staffid
            List<String> listStaffIds = new ArrayList<>();
            for (AttendDayRptVO attendDayRptVO : attendDayRptVOPages) {
                pkAttendRpt.add(attendDayRptVO.getId());
                if (StringUtils.isNotEmpty(attendDayRptVO.getDeptId()) && !listDeptIds.contains(attendDayRptVO.getDeptId())) {
                    listDeptIds.add(attendDayRptVO.getDeptId());
                }
                if (StringUtils.isNotEmpty(attendDayRptVO.getStaffId()) && !listStaffIds.contains(attendDayRptVO.getStaffId())) {
                    listStaffIds.add(attendDayRptVO.getStaffId());
                }
            }
            log.debug("获取子表数据 start");
            List<AttendRptBVO> childData = queryAttendRptbListByCommon(0, pkAttendRpt.toArray(new String[0]));
            log.debug("获取子表数据 end");
            Map<String, List<AttendRptBVO>> childMap = getchildmapBychilddata(childData);
            Map<String, String> mapDeptInfo = TranslatorToMapUtils.getDeptMap(listDeptIds);
            Map<String, String> mapStaffInfo = TranslatorToMapUtils.getFileNameMap(listStaffIds, "name");
            for (AttendDayRptVO apt : attendDayRptVOPages) {
                //部门名称
                if (mapDeptInfo.containsKey(apt.getDeptId())) {
                    apt.setDeptName(mapDeptInfo.get(apt.getDeptId()));
                }
                // 姓名
                if (mapStaffInfo.containsKey(apt.getStaffId())) {
                    apt.setStaffName(mapStaffInfo.get(apt.getStaffId()));
                }
                if (childMap.containsKey(apt.getString("id"))) {
                    List<AttendRptBVO> chidVOS = childMap.get(apt.getString("id"));
                    for (AttendRptBVO childVO : chidVOS) {
                        apt.setValue(childVO.getPkTimeitem(), childVO.getHournum());
                    }
                }
            }
            log.debug("主子表数据处理完成");
        }
        return attendDayRptVOPages;
    }

    /**
     * 日报数据查询，子表数据采用关联查询
     *
     * @param qcond
     * @param pageable
     * @param columns
     * @return
     */
    private Object newDealDay(Condition qcond, Pageable pageable, String columns) {
        long mainTableStart = System.currentTimeMillis();
        log.debug("newMethod获取主表数据 start:::{}", mainTableStart);
        Page<AttendDayRptVO> attendDayRptVOPages = getAttenddayRptByNew(qcond, pageable, columns);
        long mainTableEnd = System.currentTimeMillis();
        log.debug("newMethod获取主表数据 end:::{}", (mainTableEnd - mainTableStart));
        if (attendDayRptVOPages != null) {
            List<String> pk_attendrpt = new ArrayList<>();
            // 部门id集合
            List<String> listDeptIds = new ArrayList<>();
            // 人员id集合
            List<String> listStaffIds = new ArrayList<>();
            for (AttendDayRptVO attendDayRptVO : attendDayRptVOPages) {
                pk_attendrpt.add(attendDayRptVO.getId());
                if (StringUtils.isNotEmpty(attendDayRptVO.getDeptId()) && !listDeptIds.contains(attendDayRptVO.getDeptId())) {
                    listDeptIds.add(attendDayRptVO.getDeptId());
                }
                if (StringUtils.isNotEmpty(attendDayRptVO.getStaffId()) && !listStaffIds.contains(attendDayRptVO.getStaffId())) {
                    listStaffIds.add(attendDayRptVO.getStaffId());
                }
            }

            long subTablestart = System.currentTimeMillis();
            log.debug("newMethod获取子表数据 start:::{}", subTablestart);
            List<AttendRptBVO> childdata = queryAttendDayRptSubList(qcond,pageable);
            // List<AttendRptBVO> childdata = queryAttendDayRptSubList(qcond);
            long subTableend = System.currentTimeMillis();
            log.debug("newMethod获取子表数据 end:::{}", (subTableend - subTablestart));
            Map<String, List<AttendRptBVO>> childmap = getchildmapBychilddata(childdata);
            Map<String, String> mapDeptInfo = TranslatorToMapUtils.getDeptMap(listDeptIds);
            Map<String, String> mapStaffInfo = TranslatorToMapUtils.getFileNameMap(listStaffIds, "name");
            for (AttendDayRptVO apt : attendDayRptVOPages) {
                // 部门名称
                if (mapDeptInfo.containsKey(apt.getDeptId())) {
                    apt.setDeptName(mapDeptInfo.get(apt.getDeptId()));
                }
                // 人员名称
                if (mapStaffInfo.containsKey(apt.getStaffId())) {
                    apt.setStaffName(mapStaffInfo.get(apt.getStaffId()));
                }
                if (childmap.containsKey(apt.getString("id"))) {
                    List<AttendRptBVO> chidVOS = childmap.get(apt.getString("id"));
                    for (AttendRptBVO childVO : chidVOS) {
                        apt.setValue(childVO.getPkTimeitem(), childVO.getHournum());
                    }
                }
            }
            log.debug("主子表数据处理完成");
        }
        return attendDayRptVOPages;
    }

    private Page<AttendDayRptVO> getAttenddayRptByNew(Condition qcond, Pageable pageable, String columns) {
        //Sorter sorter=new Sorter(Sort.Direction.ASC,Arrays.asList("staff.staff_code", "staff.staff_name","staff.dept_id","day.calendar"));
        Sorter sorter = new Sorter(Sort.Direction.ASC, "staff.dept_id");
        sorter = sorter.and(new Sorter(Sort.Direction.ASC, "staff.staff_name"));
        sorter = sorter.and(new Sorter(Sort.Direction.DESC, "day.calendar"));
        return attendRptdao.queryTsdaystatList(qcond, pageable, columns, sorter);
    }


    //月报处理
    private Object dealMonth(Condition qcond, Pageable pageable, String columns) {
        Page<AttendMonthRptVO> attendMonthRptVOPages = getAttendmonthRptByNew(qcond, pageable, columns);
        if (attendMonthRptVOPages == null) return null;
        List<String> pk_attendrpt = new ArrayList<>();
        // 部门id
        List<String> listDeptIds = new ArrayList<>();
        // staffid
        List<String> listStaffIds = new ArrayList<>();
        for (AttendMonthRptVO attendMonthRptVO : attendMonthRptVOPages) {
            pk_attendrpt.add(attendMonthRptVO.getId());
            if (StringUtils.isNotEmpty(attendMonthRptVO.getDeptId()) && !listDeptIds.contains(attendMonthRptVO.getDeptId())) {
                listDeptIds.add(attendMonthRptVO.getDeptId());
            }
            if (StringUtils.isNotEmpty(attendMonthRptVO.getStaffId()) && !listStaffIds.contains(attendMonthRptVO.getStaffId())) {
                listStaffIds.add(attendMonthRptVO.getStaffId());
            }
        }
        List<AttendRptBVO> childdata = queryAttendRptbListByCommon(1, pk_attendrpt.toArray(new String[0]));
        Map<String, List<AttendRptBVO>> childmap = getchildmapBychilddata(childdata);
        Map<String, String> mapDeptInfo = TranslatorToMapUtils.getDeptMap(listDeptIds);
        Map<String, String> mapStaffInfo = TranslatorToMapUtils.getFileNameMap(listStaffIds, "name");
        for (AttendMonthRptVO apt : attendMonthRptVOPages) {
            //部门名称
            if (mapDeptInfo.containsKey(apt.getDeptId())) {
                apt.setDeptName(mapDeptInfo.get(apt.getDeptId()));
            }
            // 姓名
            if (mapStaffInfo.containsKey(apt.getStaffId())) {
                apt.setStaffName(mapStaffInfo.get(apt.getStaffId()));
            }
            if (childmap.containsKey(apt.getString("id"))) {
                List<AttendRptBVO> chidVOS = childmap.get(apt.getString("id"));
                for (AttendRptBVO childVO : chidVOS) {
                    apt.setValue(childVO.getPkTimeitem(), childVO.getHournum());
                }
            }
        }
        return attendMonthRptVOPages;
    }

    //月报处理
    private Page<AttendMonthRptVO> newDealMonth(Condition qcond, Pageable pageable, String columns, AttendRptIInfoVO attendRptIInfoVO) {
        List<AttendStaff> attendStaffList = queryAttendStaff(attendRptIInfoVO.getJobId(), attendRptIInfoVO.getStaffname());
        //如果有职务或人员信息，先根据职务和人员姓名查找人员数据，再查询月报数据，最后翻译
        if (CollectionUtils.isNotEmpty(attendStaffList)) {
            List<String> idList = com.yonyou.hrcloud.tcommon.utils.FormulaUtils.getPropertyListFromBeanVO(attendStaffList, "staffId");
            qcond.addExpression("staff_id", idList, Operator.IN);
        }
        Page<AttendMonthRptVO> attendMonthRptVOPages = (Page<AttendMonthRptVO>) dealMonthOnly(qcond, pageable, columns, attendStaffList);
        return attendMonthRptVOPages;
    }

    private Page<AttendMonthRptVO> getAttendmonthRptByNew(Condition qcond, Pageable pageable, String columns) {
        Sorter sorter = new Sorter(Sort.Direction.ASC, Arrays.asList("staff.dept_id", "staff.staff_name"));
        return attendRptdao.queryTsmonthstatList(qcond, pageable, columns, sorter);
    }

    private Page<AttendMonthRptVO> getAttendmonthRptByOnly(Condition qcond, Pageable pageable, String columns) {
        Sorter sorter = new Sorter(Sort.Direction.ASC, Arrays.asList("dept_id", "staff_code"));
        return attendRptdao.queryMonthStatOnly(qcond, pageable, columns, sorter);
    }

    private Condition getDeptIdsPowerCondNew(List<String> orgs, String staffName, Condition qcond, boolean isIncludeSub) {
        return getDeptIdsPowerCondNew(orgs, staffName, qcond,0, isIncludeSub);
    }

    private Condition getDeptIdsPowerCondNew(List<String> orgs, String staffName, Condition qcond, int reportType, boolean isIncludeSub) {
        List<String> deptid_select = orgCommonHepler.getOrgAndChildIds(orgs, "2", isIncludeSub);
        qcond.addExpression(reportType == 0 ? "staff.dept_id" : "month.dept_id", deptid_select, "in");
        if (StringUtils.isNotBlank(staffName)) {
            ChainLogicExpression cle = new ChainLogicExpression(true,
                    new ValueExpression("staff.staff_code", staffName, "like"),
                    new ValueExpression("staff.staff_name", staffName, "like"));
            qcond.addExpressions(cle);
        }
        return qcond;
    }

    /**
     * 日月报查询时获取获取下级部门
     *
     * @param orgs 部门
     * @param staffName 姓名
     * @param qcond 条件
     * @param reportType 类型
     * @param isIncludeSub 是否包含下级
     * @return
     */
    private Condition getDeptAndChildIds(List<String> orgs, String staffName, Condition qcond, int reportType, boolean isIncludeSub) {
        List<String> deptid_select = orgCommonHepler.getOrgAndChildIds(orgs, "2", isIncludeSub);
        qcond.addExpression(reportType == 0 ? "staff.dept_id" : "month.dept_id", deptid_select, "in");
        if (StringUtils.isNotBlank(staffName)) {
            ChainLogicExpression cle = new ChainLogicExpression(true,
                    new ValueExpression("staff.staff_code", staffName, "like"),
                    new ValueExpression("staff.staff_name", staffName, "like"));
            qcond.addExpressions(cle);
        }
        return qcond;
    }

    private Condition getAuditMonthCond(List<String> orgs, String staff_name, Condition qcond) {
        if (CollectionUtils.isEmpty(orgs)) return null;//如果没有部门，返回null
        if (StringUtils.isNotBlank(staff_name)) {
            qcond.addExpression("staff.dept_id", orgs, "in");
            ChainLogicExpression cle = new ChainLogicExpression(true,
                    new ValueExpression("staff.staff_code", staff_name, "like"),
                    new ValueExpression("staff.staff_name", staff_name, "like"));
            qcond.addExpressions(cle);
        } else {
            qcond.addExpression("month.dept_id", orgs, "in");
        }
        return qcond;
    }

    private Map<String, StaffInfo> getstaffmap(List<StaffInfo> staffInfos) {
        Map<String, StaffInfo> staffInfoMap = new HashMap<>();
        for (StaffInfo staffInfo : staffInfos) {
            staffInfoMap.put(staffInfo.getStaffid(), staffInfo);
        }
        return staffInfoMap;
    }

    @Override
    public List<String> getStaffidsByCond(Condition cond) {
        //处理
        try {
            List<CommonSimpleStaff> staff = simpleStaffCommonHepler.querySimpleStaffListByCondition(cond, null);
            if (CollectionUtils.isEmpty(staff)) {
                log.error(String.format("#####TM##### getStaffidsByCond:没有查询到人员-%s", JSONObject.toJSONString(cond)));
            }
            List<String> stringList = new ArrayList<>();
            staff.forEach(s -> stringList.add(s.getId()));
            return stringList;
        } catch (Exception ex) {
            log.error(String.format("#####TM##### getStaffidsByCond:没有查询到人员-%s", JSONObject.toJSONString(cond)), ex);
            throw ex;
        }
    }

    private Map<String, List<AttendRptBVO>> getchildmapBychilddata(List<AttendRptBVO> childData) {
        Map<String, List<AttendRptBVO>> childMap = new HashMap<>();
        List<AttendRptBVO> attend;
        for (AttendRptBVO vo : childData) {
            String key = vo.getPkAttendrpt();
            if (childMap.containsKey(key)) {
                childMap.get(key).add(vo);
            } else {
                attend = new ArrayList<>();
                attend.add(vo);
                childMap.put(key, attend);
            }
        }
        return childMap;
    }

    //获取日月报的布尔类型
    private List<String> getaRptAttributeNames(Object method) {
        Field[] filed = method.getClass().getDeclaredFields();
        List<String> itemBooleanTypeList = new ArrayList<>();
        int ablen = filed.length;
        for (int i = 0; i < ablen; i++) {
            String type = filed[i].getGenericType().toString();
            if ("class java.lang.Boolean".equals(type)) {
                String name = filed[i].getName();
                itemBooleanTypeList.add(name);
            }
        }
        return itemBooleanTypeList;
    }

    //获取日月报的固定列
    private JSONArray gettitleresult(Integer report_type) {
        //datatype 0:整形 1：数值型 2：字符型 3：布尔型 4：日期型
        //数据来源displayorder 0:公式计算，1:手工输入，3:固定值 4:外部类
        JSONArray jsonarry = new JSONArray();
        if (report_type == 0) {
            String fileld = LangHelper.getLangField("shift_name");
            jsonarry.add(0, addJosn("staff_code", LangHelper.getMessage("P_YS_HR_HRJQ_0000031296"), 2, 3, 0, 0));
            jsonarry.add(1, addJosn("staff_name", LangHelper.getMessage("P_YS_HR_HRJQ_0000054660"), 2, 3, 1, 0));
            jsonarry.add(2, addJosn("dept_name", LangHelper.getMessage("P_YS_HR_HRJQ_0000054659"), 2, 3, 2, 0));
            jsonarry.add(3, addJosn("calendar", LangHelper.getMessage("P_YS_FED_FW_0000021015"), 4, 3, 3, 0));
            jsonarry.add(4, addJosn(fileld, LangHelper.getMessage("P_YS_PF_GZTSYS_0000012675"), 2, 3, 4, 0));
//            jsonarry.add(5, addJosn("signbegintime", "上班打卡", 4, 3, 5, 0));
//            jsonarry.add(6, addJosn("signendtime", "下班打卡", 4, 3, 6, 0));
        } else {
            jsonarry.add(0, addJosn("staff_code", LangHelper.getMessage("P_YS_HR_HRJQ_0000031296"), 2, 3, 0, 0));
            jsonarry.add(1, addJosn("staff_name", LangHelper.getMessage("P_YS_HR_HRJQ_0000054660"), 2, 3, 1, 0));
            jsonarry.add(2, addJosn("dept_name", LangHelper.getMessage("P_YS_HR_HRJQ_0000054659"), 2, 3, 2, 0));
            jsonarry.add(3, addJosn("isapprove", LangHelper.getMessage("P_YS_HR_HRJQ_0000030919"), 3, 3, 3, 0));
        }
        return jsonarry;
    }

    private Object addJosn(String key, String name, Integer datatype, Integer displayorder, Integer sortindex, Integer iflddecimal) {
        JSONObject json = new JSONObject();

        if (key != null) {
            key = StrConversionUtils.lineToHump(key);
        }

        json.put("key", key);
        json.put("name", name);
        json.put("datatype", datatype);
        json.put("displayorder", displayorder);
        json.put("iflddecimal", iflddecimal);
        json.put("sortindex", sortindex);
        return json;
    }

    //endregion
    //region 日月报编辑保存
    @Override
    public void saveEditAttenddata(Integer report_type, JSONObject attendRptDayJson, JSONArray itemdataJson) {
        List<String> itemkeys = new ArrayList<>();
        AttendDayRptVO attendDayRptVO = new AttendDayRptVO();
        AttendMonthRptVO attendMonthRptVO = new AttendMonthRptVO();
        Map<String, String> attrs = new LinkedHashMap<>();
        int len = itemdataJson.size();
        for (int i = 0; i < len; i++) {
            Map item = (Map) itemdataJson.get(i);
            String key = (String) item.get("key");
            Integer iflddecimal = (Integer) item.get("iflddecimal");
            String columnkey = (String) item.get("columnkey");
            Integer type = (Integer) item.get("type");
            if (!"".equals(key)) {
                itemkeys.add(key);
                Object objValue = null;
                if (type != null && type == 4) {
                    if (attendRptDayJson.get(key) != null && !attendRptDayJson.get(key).equals("")) {
                        objValue = new Date((Long) attendRptDayJson.get(key));

                    }
                } else {
                    objValue = attendRptDayJson.get(key);
                    if (type != null && type == 1) {
                        if (objValue == null) {
                            objValue = new BigDecimal(0 + "").setScale(iflddecimal, BigDecimal.ROUND_HALF_UP);
                        } else {
                            objValue = new BigDecimal(objValue + "").setScale(iflddecimal, BigDecimal.ROUND_HALF_UP);
                        }
                    }

                }
                if (report_type == 0) {
                    attendDayRptVO.setValue(columnkey, objValue);
                } else {
                    attendMonthRptVO.setValue(columnkey, objValue);
                }
                attrs.put(SqlQueryHpler.getDataType(type, columnkey), columnkey.toLowerCase());
            }
        }
        Date ts = null;
        if (report_type == 0) {
            attendDayRptVO.setId(String.valueOf(attendRptDayJson.get("id")));
            attendDayRptVO.setTs(ts);
            genericService.update(attendDayRptVO, attrs);
        } else {
            attendMonthRptVO.setId(String.valueOf(attendRptDayJson.get("id")));
            attendMonthRptVO.setTs(ts);
            genericService.update(attendMonthRptVO, attrs);
        }
    }

    /***
     * 月报审核弃审
     * @param params
     */
    @Override
    public void AuditMonthRpt(AttendRptAuditParams params) {
        Condition monthcond = new Condition();
        AttendSchemeVO attendSchemeVO = null;
        if (params.isAllApprove()) {
            attendSchemeVO = getAttendSchemeVO(params.getSchemeId(), params.getDeptid(), params.isIncludeSub(), true);
            log.debug("AuditMonthRpt....attendSchemeVO.getOrgs()的个数："+attendSchemeVO.getOrgs().size());
            if (CollectionUtils.isNotEmpty(attendSchemeVO.getOrgs())) {
                monthcond.addExpression("dept_id", getInSQLCreator(attendSchemeVO.getOrgs()), "in");
            } else {
                return;
            }

            monthcond=getMonthCond(params,monthcond);
        } else {
            monthcond.addExpression("id", params.getIds(), "in");
            if(StringUtils.isNotBlank(params.getSchemeId())){
                attendSchemeVO = genericService.load(AttendSchemeVO.class,params.getSchemeId());
            }
        }

        //更新月报的审核状态
        List<AttendMonthRptVO> monthRptVOS=attendRptdao.querymonthByCondition(monthcond,null);
        if(CollectionUtils.isEmpty(monthRptVOS)){
            return;
        }
        //审核月报
        String aprroveStatus=params.isApprove()?"1":"0";
        attendRptdao.AuditMonthRpt(monthcond,aprroveStatus);
        //审核日报
        attendRptdao.AuditDayRpt(getDayCond(monthRptVOS),aprroveStatus);
        //异步处理NCC同步
        params.setTenantId(AppContext.getContext().getScope());
        params.setUserId(AppContext.getContext().getUserId());
        if (attendSchemeVO == null) {
            return;
        }
        params.setMonthRptVOS(monthRptVOS);
        attendRptAsyncService.processMonthDataSyn2NCC(params, attendSchemeVO, NCCAsyncParam.generate());
    }

    private String getInSQLCreator(List<String> list){
        if(CollectionUtils.isEmpty(list)){
            return "'1=2'";
        }
        InSQLCreator isc = new InSQLCreator();
        String strInSql;
        try {
            strInSql = isc.getInSQL(list.toArray(new String[0]));
        } catch (Exception e) {
            throw new AdderBusinessException(e.getMessage(),e,null);
        }
        log.error("strInSql:..."+strInSql);
        if("(".equals(strInSql.substring(0,1))){
            strInSql=strInSql.substring(1,strInSql.length()-1);
        }
        return strInSql;
    }

    private Condition getMonthCond(AttendRptAuditParams params,Condition monthcond){
        monthcond.addExpression("tsyear", params.getYear());
        monthcond.addExpression("tsmonth", params.getMonth());
        if (StringUtils.isNoneBlank(params.getStaffname())){
            //如果有人员模糊查询，还走之前的逻辑(需要关联attendstaff)
            Condition condition = new Condition();
            ChainLogicExpression cle = new ChainLogicExpression(true,
                    new ValueExpression("staff_code", params.getStaffname(), Operator.LIKEANY),
                    new ValueExpression("staff_name", params.getStaffname(), Operator.LIKEANY));
            condition.addExpressions(cle);
            List<AttendStaff> attendStaffs = attendStaffService.queryByConditon(condition, null);
            List<String> staffIds=FormulaUtils.getPropertyListFromBeanVO(attendStaffs,"staffId");
            if (CollectionUtils.isNotEmpty(attendStaffs)) {
                //更新月报审核状态
                monthcond.addExpression("staff_id", getInSQLCreator(staffIds),Operator.IN);
            }
        }
        return monthcond;
    }
    //组件日报的条件
    private Condition getDayCond(List<AttendMonthRptVO> monthRptVOS){
        Condition dayCond=new Condition();

        List<String> staffMonthIds=FormulaUtils.getPropertyListFromBeanVO(monthRptVOS,"staffId");
        //一个假勤期间的开始日期和结束日期是一致的
        Date begindate = monthRptVOS.get(0).getBegindate();
        Date enddate = monthRptVOS.get(0).getEnddate();
        //组件日报的条件
        dayCond.addExpression("staff_id",getInSQLCreator(staffMonthIds),Operator.IN);
        dayCond.addExpression("calendar", begindate, ">=");
        dayCond.addExpression("calendar", enddate, "<=");
        return dayCond;
    }
    //endregion
    //region生成外部调用接口

    /**
     * 获取考勤日报根据人员ID和日期生成的集合
     *
     * @param beginDate 查询开始日期
     * @param endDate   查询结束日期
     * @return
     */
    @Override
    public Map<String, Map<String, AttendDayRptVO>> querySumDayByCondition(String[] staffIds, Date beginDate, Date endDate, String itemMainId, String leaveRuleId) {
        if (ArrayUtils.isEmpty(staffIds)) {
            return new HashMap<>();
        }
        Condition cond = new Condition();
        Map<String, Map<String, AttendDayRptVO>> mapSumDayOrgInfo = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            cond.addExpression("day.staff_id", staffIds, Operator.IN);
            beginDate = sdf.parse(sdf.format(beginDate));
            cond.addExpression("day.calendar", beginDate, Operator.GREATEREQUAL);
            endDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(sdf.format(endDate) + " " + "23:59:59");
            cond.addExpression("day.calendar", endDate, Operator.LESSEQAUL);
        } catch (ParseException e) {
            log.error("querySumDayByCondition error:", e);
        }
        StringBuilder sumcode = new StringBuilder();
        List<TimeItemVO> itemVOList = itemService.queryTimeItemsExt(itemMainId, leaveRuleId, "0", false, null);
        for (TimeItemVO timevo : itemVOList) {
            if (timevo.getIdatatype() == 0 || timevo.getIdatatype() == 1) {
                sumcode.append("sum(").append(timevo.getDbcode()).append(") ").append(timevo.getDbcode()).append(",");
            }
        }
        if (sumcode.length() > 0) {
            String cloumns = sumcode.substring(0, sumcode.length() - 1);
            List<AttendDayRptVO> attendDayRptVOS = attendRptdao.queryTsSumdaystatList(cond, cloumns, null);
            for (AttendDayRptVO attendDayRptVO : attendDayRptVOS) {
                processCustomeItem(attendDayRptVO);
                if (mapSumDayOrgInfo.containsKey(attendDayRptVO.getStaffId())) {
                    mapSumDayOrgInfo.get(attendDayRptVO.getStaffId()).put(attendDayRptVO.getOrgId(), attendDayRptVO);
                } else {
                    Map<String, AttendDayRptVO> tmpMap = new HashMap<>();
                    tmpMap.put(attendDayRptVO.getOrgId(), attendDayRptVO);
                    mapSumDayOrgInfo.put(attendDayRptVO.getStaffId(), tmpMap);
                }
            }
            if (CollectionUtils.isNotEmpty(attendDayRptVOS)) {
                log.debug(String.format("###attend querySumDayByCondition-汇总日报信息:cond---%s,columns---%s,result[0]---%s", JSONObject.toJSONString(cond), cloumns, JSONObject.toJSONString(attendDayRptVOS.get(0))));
            }
        }
        return mapSumDayOrgInfo;
    }

    /***
     * 处理汇总自定义项目问题
     * @param rptVO
     */
    private void processCustomeItem(AttendDayRptVO rptVO) {
        Map<String, Object> tempData = rptVO.tempData();
        if (MapUtils.isEmpty(tempData)) return;
        Map<String, Object> customerData = new HashMap<>();
        for (String key : tempData.keySet()) {
            if (key.startsWith("fI")) {
                customerData.put(key.replace("fI", "f_i_"), tempData.get(key));
            } else if (key.startsWith("fN")) {
                customerData.put(key.replace("fN", "f_n_"), tempData.get(key));
            }
        }
        if (MapUtils.isNotEmpty(customerData))
            tempData.putAll(customerData);
    }

    /**
     * 获取考勤月报上月数据
     *
     * @param staffid 人员ID数组
     * @param year    查询年
     * @param month   查询月
     * @return
     */
    @Override
    public Map<String, AttendMonthRptVO> queryLastMonthByCondition(String[] staffid, String year, String month) {
        Condition cond = new Condition();
        Map<String, AttendMonthRptVO> attendMonthRptMapByStaffid = new HashMap<>();
        if (staffid != null && staffid.length > 0) {
            cond.addExpression("staff_id", staffid, "in");
        }

        if (null != year && !"".equals(year)) {
            cond.addExpression("tsyear", year);
        }
        if (null != month && !"".equals(month)) {
            cond.addExpression("tsmonth", month);
        }
        List<AttendMonthRptVO> attendMonthRptVOS = attendRptdao.querymonthByCondition(cond, null);
        for (AttendMonthRptVO attendMonth : attendMonthRptVOS) {
            if (!attendMonthRptMapByStaffid.containsKey(attendMonth.getStaffId()))
                //TODO 对于_tempdata里面的数据进行驼峰处理
                doHump(attendMonth);
            attendMonthRptMapByStaffid.put(attendMonth.getStaffId(), attendMonth);
        }
        return attendMonthRptMapByStaffid;
    }

    private void doHump(AttendMonthRptVO attendMonth){
        Map<String, Object> tempdata = attendMonth.tempData();
        if(MapUtils.isEmpty(tempdata)){
            return;
        }
        String temp = JSON.toJSONString(tempdata).replaceAll("fB", "f_b_").replaceAll("fD", "f_d_").replaceAll("fI", "f_i_")
                .replaceAll("fN", "f_n_").replaceAll("fV", "f_v_");
        if(gson==null){
            gson=new Gson();
        }
        Map<String, Object> humpMap = gson.fromJson(temp, tempdata.getClass());
        attendMonth.tempData().putAll(humpMap);
    }


    /***
     * 查询月报数据(按组织分组)
     * @param staffid
     * @param year
     * @param month
     * @param deptIds
     * @return
     */
    @Override
    public Map<String, AttendMonthRptVO> queryMonthRptGroupByOrg(String[] staffid, String year, String month, List<String> deptIds) {
        Condition cond = new Condition();
        Map<String, AttendMonthRptVO> mapResult = new HashMap<>();
        if (ArrayUtils.isEmpty(staffid)) return mapResult;
        cond.addExpression("staff_id", staffid, "in");
        cond.addExpression("tsyear", year);
        cond.addExpression("tsmonth", month);
        cond.addExpression("dept_id", deptIds, Operator.IN);
        List<AttendMonthRptVO> attendMonthRptVOS = attendRptdao.querymonthByCondition(cond, null);
        for (AttendMonthRptVO attendMonth : attendMonthRptVOS) {
            String key = String.format("%s_%s", attendMonth.getStaffId(), attendMonth.getOrgId());
            if (!mapResult.containsKey(key)) {
                mapResult.put(key, attendMonth);
            }
        }
        return mapResult;
    }

    //endregion
    //region 导入导出

    /**
     * 获取考勤日月报导出
     *
     * @return
     */
    @Override
    public Workbook exportAttendRptdata(String schemeId, AttendRptIInfoVO attendRptIInfoVO) {
        log.info("get export excel data");
        Pageable pageable = new PagerRequest(0, 99999);
        Workbook workbook;
        Map<String, Object> data = (Map<String, Object>) dealDayAndMonthCommon(schemeId, attendRptIInfoVO.getReport_type(), attendRptIInfoVO.getStaffname(), attendRptIInfoVO.getDeptid(), true, attendRptIInfoVO.getCon(), pageable);
        JSONArray titleList = (JSONArray) data.get("title");
        if (attendRptIInfoVO.getReport_type() == 0) {
            Page<AttendDayRptVO> attendRptPages = (Page<AttendDayRptVO>) data.get("data");
            if (attendRptPages != null) {
                attendRptIInfoVO.setAttendDayList(attendRptPages.getContent());
            }
            attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getBeginDateStr() + "-" + attendRptIInfoVO.getEndDateStr());
            attendRptIInfoVO.setSheetname(MultilingualTranslateHelper.getLeaveProgramme() + this.attendSchemeVOName + MultilingualTranslateHelper.getAttendanceDailyFileName());
        } else {
            Page<AttendMonthRptVO> attendRptPages = (Page<AttendMonthRptVO>) data.get("data");
            if (attendRptPages != null) {
                attendRptIInfoVO.setAttendMonthList(attendRptPages.getContent());
            }
            if (attendRptIInfoVO.getYear() != null && attendRptIInfoVO.getMonth() != null) {
                attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getYear() + "-" + attendRptIInfoVO.getMonth());
            }
            attendRptIInfoVO.setSheetname(MultilingualTranslateHelper.getLeaveProgramme() + this.attendSchemeVOName + MultilingualTranslateHelper.getAttendanceDailyFileName());
        }
        attendRptIInfoVO.setCorpName("");
        attendRptIInfoVO.setTitlecolumnList(titleList);
        log.info("export excel start");
        workbook = TsAttendRptUtils.exportExcel(attendRptIInfoVO);
        log.info("export excel end");
        return workbook;
    }

    /**
     * 导出日月报新方法
     *
     * @param schemeId
     * @param attendRptIInfoVO
     * @return
     */
    @Override
    public Workbook newExportAttendRptdata(String schemeId, AttendRptIInfoVO attendRptIInfoVO, String fileName) {
        Workbook workbook = newExportExcel(schemeId, attendRptIInfoVO, fileName);
        return workbook;
    }

    /**
     * 导出数据对象到Excel文件
     *
     * @param attendRptIInfoVO
     * @return
     */
    public Workbook newExportExcel(String schemeId, AttendRptIInfoVO attendRptIInfoVO, String fileName) {
        int reportType = attendRptIInfoVO.getReport_type();
        long excelTitleTimeStart = System.currentTimeMillis();
        log.debug("newMethod获取表头start:::{}", excelTitleTimeStart);
        Map<String, Object> titleResult = getTitle(schemeId, reportType, attendRptIInfoVO);
        long excelTitleTimeEnd = System.currentTimeMillis();
        log.debug("newMethod获取表头end:::{}", (excelTitleTimeEnd - excelTitleTimeStart));
        AttendSchemeVO attendSchemeVO = (AttendSchemeVO) titleResult.get("attendSchemeVO");

        //获取数据总条数
        log.debug("newMethod获取数据总条数start");
        Map<String, Object> dataNum = getDayAndMonthTotalNum(reportType, attendSchemeVO, attendRptIInfoVO);
        long totalNumEnd = System.currentTimeMillis();
        log.debug("newMethod获取数据总条数end:::{}", (totalNumEnd - excelTitleTimeEnd));
        //通过当前语种获取假勤方案名称
        String attendSchemeVOName = MultiLangHelper.getLangName(attendSchemeVO, "name");
        int totalRowCount;
        String leaveProgramme = MultilingualTranslateHelper.getLeaveProgramme();
        if (reportType == 0) {
            String attendDaily = MultilingualTranslateHelper.getAttendanceDailyFileName();
            totalRowCount = Integer.valueOf(String.valueOf(dataNum.get("dayRptNum") == null ? 0 : dataNum.get("dayRptNum")));
            attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getBeginDateStr() + "-" + attendRptIInfoVO.getEndDateStr());
            attendRptIInfoVO.setSheetname(leaveProgramme + " " + attendSchemeVOName + " " + attendDaily);
        } else {
            String attendMonthly = MultilingualTranslateHelper.getAttendanceMonthlyFileName();
            totalRowCount = Integer.valueOf(String.valueOf(dataNum.get("monthRptNum") == null ? 0 : dataNum.get("monthRptNum")));
            attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getYear() + "-" + attendRptIInfoVO.getMonth());
            attendRptIInfoVO.setSheetname(leaveProgramme + " " + attendSchemeVOName + " " + attendMonthly);
        }
        attendRptIInfoVO.setCorpName("");

        // 初始化EXCEL
        long initExcelStart = System.currentTimeMillis();
        log.debug("newMethod初始化EXCEL start:::{}", initExcelStart);
        SXSSFWorkbook wb = PoiUtil.initExcel(totalRowCount, attendRptIInfoVO);
        long initExcelEnd = System.currentTimeMillis();
        log.debug("newMethod初始化EXCEL end:::{}", (initExcelEnd - initExcelStart));
        // 如果没有查到数据返回空excel
        if (totalRowCount == 0) {
            return wb;
        }

        CellStyle cellStyleHead = PoiUtil.getRowCell(wb, false);
        Condition qcond = attendRptIInfoVO.getCon();
        // qcond = getDeptIdsPowerCondNew(attendSchemeVO.getOrgs(),staffName,qcond);
        // 分表单写数据
        int sheetCount = wb.getNumberOfSheets();
        int currentPage = 0;
        for (int i = 0; i < sheetCount; i++) {
            SXSSFSheet eachSheet = (SXSSFSheet) wb.getSheetAt(i);
            //计算剩下的数据数量，
            int lastNum = totalRowCount;
            if (i > 0) {
                lastNum = totalRowCount - i * ExcelConstant.PER_SHEET_ROW_COUNT;
            }
            //每个表单写数据次数
            int perSheetWriteNum = ExcelConstant.getPerSheetWriteNum(lastNum);
            // 分批写数据，每页去掉表头应该从第几行开始
            int dataStartRow = eachSheet.getLastRowNum() + 1;
            long batchStart = System.currentTimeMillis();
            log.debug("newMethod分批写数据start{}", batchStart);
            for (int j = 1; j <= perSheetWriteNum; j++) {
                int pageSize = ExcelConstant.PER_WRITE_ROW_COUNT;
                int startRowIndex = (j - 1) * ExcelConstant.PER_WRITE_ROW_COUNT + dataStartRow;
                log.debug("当前页码pageSize:" + pageSize + "开始行:" + startRowIndex + "当前页码：" + currentPage);
                //查询数据写入sheet表单
                writeData(eachSheet, cellStyleHead, qcond, currentPage, pageSize, startRowIndex, titleResult, attendRptIInfoVO, attendSchemeVO);
                currentPage = ++currentPage;
            }
            long batchEnd = System.currentTimeMillis();
            log.debug("newMethod分批写数据end{}", (batchEnd - batchStart));
        }
        return wb;
    }


    private void writeData(SXSSFSheet eachSheet, CellStyle cellStyleHead, Condition qcond, int currentPage, int pageSize, int startRowIndex, Map<String, Object> titleResult, AttendRptIInfoVO attendRptIInfoVO, AttendSchemeVO attendSchemeVO) {
        //获取数据,
        int reportType = attendRptIInfoVO.getReport_type();
        Pageable dataPageable = new PagerRequest(currentPage, pageSize);
        String columns = String.valueOf(titleResult.get("columns"));
        long getDataTimeStart = System.currentTimeMillis();
        log.debug("newMethod获取数据start:::{}", getDataTimeStart);
        //主表数据
        if (attendSchemeVO.getOrgs() != null && attendSchemeVO.getOrgs().size() > 0) {
            if (reportType == 0) {
                qcond = getDeptIdsPowerCondNew(attendSchemeVO.getOrgs(), attendRptIInfoVO.getStaffname(), qcond, attendRptIInfoVO.isIncludeSub());
                Object qdata = newDealDay(qcond, dataPageable, columns);
                Page<AttendDayRptVO> attendRptPages = (Page<AttendDayRptVO>) qdata;
                if (attendRptPages != null) {
                    attendRptIInfoVO.setAttendDayList(attendRptPages.getContent());
                }
            } else {
                List<String> deptid_select = orgCommonHepler.getOrgAndChildIds(attendSchemeVO.getOrgs(), "2", attendRptIInfoVO.isIncludeSub());
                qcond.addExpression("dept_id", deptid_select, "in");
                Object qdata = newDealMonth(qcond, dataPageable, columns, attendRptIInfoVO);
                Page<AttendMonthRptVO> attendRptPages = (Page<AttendMonthRptVO>) qdata;
                if (attendRptPages != null) {
                    attendRptIInfoVO.setAttendMonthList(attendRptPages.getContent());
                }
            }
        }
        long getDataTimeEnd = System.currentTimeMillis();
        log.debug("newMethod获取数据end:::{}", (getDataTimeEnd - getDataTimeEnd));

        JSONArray titleList = (JSONArray) titleResult.get("titleList");
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("attendRptIInfoVO", attendRptIInfoVO);
        paramMap.put("sheet", eachSheet);//传入表单
        paramMap.put("cellStyleHead", cellStyleHead);//传入表头格式
        paramMap.put("titleList", titleList);//传入列表头
        //将数据写入excel表
        long writeDataTimeStart = System.currentTimeMillis();
        log.debug("newMethod写入数据表start:::", writeDataTimeStart);
        createSheetBody(paramMap, startRowIndex);
        long writeDataTimeEnd = System.currentTimeMillis();
        log.debug("newMethod写入数据表end:::{}", (writeDataTimeEnd - writeDataTimeStart));
    }

    /**
     * 获取表头数据
     *
     * @param schemeId
     * @param reportType
     * @param attendRptIInfoVO
     * @return
     */
    private Map<String, Object> getTitle(String schemeId, int reportType, AttendRptIInfoVO attendRptIInfoVO) {
        String deptId = attendRptIInfoVO.getDeptid();
        boolean isIncludeSub = attendRptIInfoVO.isIncludeSub();
        boolean isPower = true;
        long attendSchemeVOstart = System.currentTimeMillis();
        log.info("######## month #### newMethod  dealDayAndMonthCommon begin " + deptId);
        AttendSchemeVO attendSchemeVO = getAttendSchemeVOWeb(schemeId, deptId, isIncludeSub, isPower);
        long attendSchemeVOend = System.currentTimeMillis();
        log.info("######## month #### newMethod " + (attendSchemeVOend - attendSchemeVOstart) + "  dealDayAndMonthCommon end " + deptId);
        if (attendSchemeVO == null) {
            throw new AdderBusinessException("没有对应的假勤方案！", "attend.report.i18n59");
        }
        Map<String, Object> titleData = queryViewOrderMapByScheme(attendSchemeVO, reportType);
        long titleDataend = System.currentTimeMillis();
        log.info("######## month #### newMethod :::" + (titleDataend - attendSchemeVOend) + " dealDayAndMonthCommon queryVieworderMap");
        List<AttendVieworderRptVO> showOrderList = new ArrayList<>();
        if (titleData != null) {
            showOrderList = (List<AttendVieworderRptVO>) titleData.get("showorderlist");
        }
        if (showOrderList.size() == 0) {
            log.error("请至少选择一个栏目！");
            throw new AdderBusinessException("请至少选择一个栏目！", "attend.report.i18n46");
        }
        Map<String, Object> reaultMap = getTitleData(reportType, showOrderList);
        attendRptIInfoVO.setTitlecolumnList((JSONArray) reaultMap.get("titleList"));
        reaultMap.put("attendSchemeVO", attendSchemeVO);
        return reaultMap;
    }

    /**
     * 创建Sheet体
     */
    private static void createSheetBody(Map<String, Object> paramMap, int startRowIndex) {
        AttendRptIInfoVO attendRptIInfoVO = (AttendRptIInfoVO) paramMap.get("attendRptIInfoVO");
        int reportType = attendRptIInfoVO.getReport_type();
        paramMap.put("reportType", reportType);
//    	处理日报数据
        if (reportType == 0 && attendRptIInfoVO.getAttendDayList() != null) {
            for (int i = 0; i < attendRptIInfoVO.getAttendDayList().size(); i++) {
                AttendDayRptVO attendDayRptVO = attendRptIInfoVO.getAttendDayList().get(i);
                //往行内写数据
                addSheetData(paramMap, startRowIndex + i, attendDayRptVO);
            }
        }
//    	处理月报数据
        if (reportType == 1 && attendRptIInfoVO.getAttendMonthList() != null) {
            for (int i = 0; i < attendRptIInfoVO.getAttendMonthList().size(); i++) {
                AttendMonthRptVO attendMonthRptVO = attendRptIInfoVO.getAttendMonthList().get(i);
                //往行内写数据
                addSheetData(paramMap, startRowIndex + i, attendMonthRptVO);
            }
        }
    }

    /**
     * @Author: wangwy
     * @param: [paramMap, rowNum, obj]
     * @return: void
     * @Date: 2019/7/6 15:33
     * 给Sheet添加数据
     */
    private static void addSheetData(Map<String, Object> paramMap, int rowNum, Object obj) {
        //取出参数
        SXSSFSheet sheet = (SXSSFSheet) paramMap.get("sheet");
        JSONArray titleList = (JSONArray) paramMap.get("titleList");
        CellStyle cellStyleHead = (CellStyle) paramMap.get("cellStyleHead");
        int reportType = Integer.valueOf(String.valueOf(paramMap.get("reportType")));
        //执行逻辑
        Row row = sheet.createRow(rowNum);
        for (int cellnum = 0; cellnum < titleList.size(); cellnum++) {
            Cell cell = row.createCell(cellnum);// 创建列
            cell.setCellType(CellType.STRING);
            if(reportType == 0) {
                cell.setCellStyle(cellStyleHead);
            }
            Map o = (Map) titleList.get(cellnum);
            String key = (String) o.get("key");
            Integer type = (Integer) o.get("datatype");
            Integer iflddecimal = (Integer) o.get("iflddecimal");
            //用java反射获取传入对象的值，
            Object value = getValueByKey(obj, key);
            if (reportType == 0) {
                if ("signendtime".equals(key) || "signbegintime".equals(key)) {
                    type = 5;
                }
            }
            // 按照数据类型设置单元格数据
            TsAttendRptUtils.setFieldValueByType(cell, type, value, iflddecimal);
//            cell.setCellValue(getFieldValueByType(type, value, iflddecimal));
        }
    }

    /**
     * 使用反射获取对象中指定属性的值
     *
     * @param obj
     * @param key
     * @return
     */
    private static Object getValueByKey(Object obj, String key) {
        // 得到类对象
        Class objClass = (Class) obj.getClass();

        /* 得到类中的所有属性集合,包括父类的属性 */
        List<Field> fieldList = new ArrayList<Field>();
        while (objClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(objClass.getDeclaredFields()));
            objClass = objClass.getSuperclass(); //得到父类,然后赋给自己
        }
        Map<String, Object> tempDataMap = null;
        for (int i = 0; i < fieldList.size(); i++) {
            Field f = fieldList.get(i);
            f.setAccessible(true); // 设置些属性是可以访问的
            try {
                if (f.getName().equals(key)) {
                    return f.get(obj);
                } else if (f.getName().equals("_tempData")) {
                    tempDataMap = (Map<String, Object>) f.get(obj);
                }
            } catch (IllegalArgumentException e) {
                //e.printStackTrace();
            } catch (IllegalAccessException e) {
                //e.printStackTrace();
            }
        }
//        如果没有找到值再去_tempData中查找
        if (tempDataMap != null && tempDataMap.size() > 0) {
            return tempDataMap.get(key);
        }
        // 没有查到时返回空字符串
        return "";
    }

    /**
     * 根据属性名获取属性值
     *
     * @param type        数据类型 0:整形 1：数值型 2：字符型 3：布尔型 4：日期型
     * @param value
     * @param iflddecimal
     */
    private static String getFieldValueByType(Integer type, Object value, Integer iflddecimal) {
        String resultvalue = "";
        value = dealValue(value);
        if (value != null || type == 3) {
            switch (type) {
                case 0:
                    String Ivalue = String.valueOf(value);
                    if (!"0".equals(Ivalue))
                        resultvalue = Ivalue;
                    break;
                case 1:
                    NumberFormat nf = NumberFormat.getNumberInstance();
                    if (iflddecimal == null) {
                        iflddecimal = 0;
                    }
                    nf.setMaximumFractionDigits(iflddecimal);
                    if (value == null || "".equals(value)) {
                        value = 0;
                    }
                    if (!"0".equals(String.valueOf(nf.format(value)))) {
                        resultvalue = String.valueOf(nf.format(value));
                    }
                    break;
                case 3:
                    String bvalue = String.valueOf(value);
                    if ("1".equals(bvalue) || "true".equals(bvalue)) {
                        resultvalue = MultilingualTranslateHelper.getYes();
                    } else {
                        resultvalue = MultilingualTranslateHelper.getNo();
                    }
                    break;
                case 4:
                    Date dvalue = null;
                    if (value != null && !"".equals(value)) {
                        dvalue = (Date) value;
                    }
                    resultvalue = DateUtil.DateToString(dvalue, DateStyle.YYYY_MM_DD);
                    break;
                case 5:
                    Date Tvalue = null;
                	/*if(value == null || "".equals(value)) {
                		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                		try {
                			Tvalue = df.parse("1970-01-01");
						} catch (ParseException e) {
							//e.printStackTrace();
						}

                	}else {
                		Tvalue = (Date) value;
                	}*/
                    if (value != null && !"".equals(value)) {
                        Tvalue = (Date) value;
                    }
                    resultvalue = DateUtil.DateToString(Tvalue, DateStyle.HH_MM_SS);
                    break;
                default:
                    resultvalue = String.valueOf(value);
                    break;
            }
        }
        return resultvalue;
    }

    private static Object dealValue(Object value) {
        //正常考勤处理
        if (TimeConst.ATTEND_TYPE_YES.equals(value))
            value = "正常考勤";
        else if (TimeConst.ATTEND_TYPE_NO.equals(value))
            value = "不考勤";
        else if (TimeConst.ATTEND_TYPE_NOSIGN.equals(value))
            value = "免签到";
        return value;
    }

    /**
     * 获取考勤日月报模板导出
     *
     * @return
     */
    @Override
    public Workbook exportAttendRptTemplet(String schemeId, AttendRptIInfoVO attendRptIInfoVO) {
        Workbook workbook;
        Integer report_type = attendRptIInfoVO.getReport_type();
        AttendSchemeVO attendSchemeVO = getAttendSchemeVO(schemeId, attendRptIInfoVO.getDeptid(), true, true);
        Map<String, Object> data = queryVieworderMap(attendSchemeVO.getItemSchemeId(), attendSchemeVO.getLeaveRuleId(), report_type);
        List<AttendVieworderRptVO> showorderlist = new ArrayList<>();
        if (data != null) {
            showorderlist = (List<AttendVieworderRptVO>) data.get("showorderlist");
        }
        if (data == null || showorderlist.size() == 0) {
            log.error("请至少选择一个栏目！");
            throw new AdderBusinessException("请至少选择一个栏目！", "attend.report.i18n46");
        }
        Map<String, Object> titleresult = getTitleData(report_type, showorderlist);
        JSONArray titleList = (JSONArray) titleresult.get("titleList");
        if (report_type == 0) {
            Page<AttendDayRptVO> attendRptPages = (Page<AttendDayRptVO>) data.get("data");
            if (attendRptPages != null) {
                attendRptIInfoVO.setAttendDayList(attendRptPages.getContent());
            }
            attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getBeginDateStr() + "-" + attendRptIInfoVO.getEndDateStr());
            attendRptIInfoVO.setSheetname(MultilingualTranslateHelper.getAttendanceDailyFileName());
        } else {
            Page<AttendMonthRptVO> attendRptPages = (Page<AttendMonthRptVO>) data.get("data");
            if (attendRptPages != null) {
                attendRptIInfoVO.setAttendMonthList(attendRptPages.getContent());
            }
            attendRptIInfoVO.setPeriodStr(attendRptIInfoVO.getYear() + "-" + attendRptIInfoVO.getMonth());
            attendRptIInfoVO.setSheetname(MultilingualTranslateHelper.getAttendanceMonthlyFileName());
        }
        JSONArray titlecolumnList = new JSONArray();
        List<String> keys = new ArrayList<>();

        Collections.addAll(keys, attendRptIInfoVO.getColumnkeys());

        for (int i = 0; i < titleList.size(); i++) {
            Map o = (Map) titleList.get(i);
            String key = String.valueOf(o.get("key"));
            if ("staffCode".equals(key) || "staffName".equals(key) || "calendar".equals(key) || keys.contains(key)) {
                titlecolumnList.add(o);
            }
        }
        attendRptIInfoVO.setCorpName("");
        attendRptIInfoVO.setTitlecolumnList(titlecolumnList);
        workbook = TsAttendRptUtils.exportExcel(attendRptIInfoVO);
        return workbook;
    }

    /**
     * 获取考勤日月报导入
     *
     * @return
     */
    @Override
    public Object readExcelToDB(AttendRptIInfoVO attendRptIInfoVO) {
        // 读取Excel到VO
        return readeExcelVO(attendRptIInfoVO);
    }

    private Object readeExcelVO(AttendRptIInfoVO attendRptIInfoVO) {
        List<List<String>> listList;
        try {
            listList = TsAttendRptUtils.readbusiDataFromExcel(attendRptIInfoVO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new AdderBusinessException("读取Excel文件错误:", "attend.report.i18n47", e.getMessage());
        }
        if (listList != null && listList.size() > 2) {
            //获取考勤人员
            AttendSchemeVO attendSchemeVO = getAttendSchemeVO(attendRptIInfoVO.getMainid(), attendRptIInfoVO.getDeptid(), true, true);
            List<AttendStaff> attendStaffList = staffAttendCommonService.queryAttendStaffListByCond(null, attendSchemeVO.getOrgs());
            Map<String, AttendStaff> attendStaffMap = attendStaffList.stream().collect(Collectors.toMap(AttendStaff::getStaffCode, a -> a, (a1, a2) -> a1));
            if (attendStaffMap == null || attendStaffMap.size() == 0) {
                throw new AdderBusinessException("请先生成考勤人员！", "attend.report.i18n48");
            }
            //获取考勤项目集合
            Integer report_type = attendRptIInfoVO.getReport_type();
            Condition condition = new Condition();
            if (report_type != null) {
                condition.addExpression("itemtype", report_type);
            }
            String main_id = getItemmainId(attendRptIInfoVO.getMainid());
            if (!StringUtils.isEmpty(main_id)) {
                condition.addExpression("main_id", main_id);
            }
            List<TimeItemVO> itemVOList = itemService.queryItemList(condition, new Sorter(Sort.Direction.ASC, "icomputeseq"));
            List<TimeItemVO> extitemVOList = itemService.queryTimeItemsOnlyExt(attendSchemeVO);
            if (report_type == 0) {
                dealDayImport(listList, itemVOList, extitemVOList, attendStaffMap, attendSchemeVO.getId());
            } else {
                dealMonthImport(listList, itemVOList, extitemVOList, attendStaffMap, attendSchemeVO);
            }
        }
        return null;
    }

    //处理日报数据
    private void dealDayImport(List<List<String>> listList, List<TimeItemVO> timeItemVOS, List<TimeItemVO> extitemVOList, Map<String, AttendStaff> attendStaffMap, String secamid) {
        //获取数据集合
        List<AttendDayRptVO> insertlist = new ArrayList<>();
        Map<String, Object> timeItemVoName = FormulaUtils.getPropertyMapFromBeanVO(timeItemVOS, "name");
        List<String> keylist = null;
        List<String> datalist = null;
        int listListlen = listList.size();
        Date begindate = null;
        Date enddate = null;
        List<String> cloumns = new ArrayList<>();
        if (listListlen > 3) {
            keylist = listList.get(2);
            TimeItemVO timeItemVO = null;
            AttendDayRptVO attendDayRptVO = null;
            AttendStaff attendStaff = null;
            List<String> impstaffids = new ArrayList<>();
            for (int i = 3; i < listListlen; i++) {
                datalist = listList.get(i);
                if (datalist.size() == 0) {
                    continue;
                }
                String staff_code = String.valueOf(datalist.get(0)).replace(".0", "");
                if ("".equals(String.valueOf(staff_code))) {
                    continue;
                }
                attendStaff = attendStaffMap.get(staff_code);
                if (attendStaff == null)
                    throw new AdderBusinessException("人员编码[{0}]不存在", "attend.report.i18n49", staff_code);
                Object calendarvalue = datalist.get(2);
                if (TsAttendRptUtils.isBlank(calendarvalue) || !DateUtil.isDate(String.valueOf(calendarvalue))) {
                    throw new AdderBusinessException("人员编码[{0}]，日期{1}不合法", "attend.report.i18n50",
                            new String[]{staff_code, String.valueOf(calendarvalue)});
                }
                Date calendar = DateUtil.StringToDate(String.valueOf(calendarvalue), DateStyle.YYYY_MM_DD);
                if (begindate != null) {
                    if (begindate.getTime() > calendar.getTime()) {
                        begindate = calendar;
                    }
                } else {
                    begindate = calendar;
                }
                if (enddate != null) {
                    if (enddate.getTime() < calendar.getTime()) {
                        enddate = calendar;
                    }
                } else {
                    enddate = calendar;
                }
                //检验是否考勤人员
                if (CalendarCommon.checkActivedDate(attendStaffMap, attendStaff.getStaffCode(), String.valueOf(calendarvalue))) {
                    throw new AdderBusinessException("人员编码[{0}]不存在", "attend.report.i18n49", staff_code);
                }
                impstaffids.add(attendStaff.getStaffId());
            }

            // 查询当前日期范围内的考勤日报数据
            if (impstaffids.size() == 0) {
                return;
            }
            Condition rptCond = new Condition();
            rptCond.addExpression("calendar", begindate, ">=");
            rptCond.addExpression("calendar", enddate, "<=");
            rptCond.addExpression("staff_id", impstaffids, "in");
            Sorter sorter = new Sorter("staff_id");
            List<AttendDayRptVO> rptVos = queryAttendDayRptVOLit(rptCond, sorter);
            Map<String, Map<Date, AttendDayRptVO>> stringMapMap = getRptMap(rptVos);
            for (int i = 3; i < listListlen; i++) {
                datalist = listList.get(i);
                if (datalist.size() == 0)
                    continue;
                int datalistLen = datalist.size();

                String staff_code = String.valueOf(datalist.get(0)).replace(".0", "");
                if ("".equals(String.valueOf(staff_code))) {
                    continue;
                }
                attendStaff = attendStaffMap.get(staff_code);
                if (attendStaff == null)
                    throw new AdderBusinessException("考勤人员档案中人员编码[{0}]不存在或为“不考勤”,不允许导入！请在假勤档案中重新设置员工的考勤方式！", "attend.report.i18n51", staff_code);
                Object calendarvalue = datalist.get(2);
                if (TsAttendRptUtils.isBlank(calendarvalue) || !DateUtil.isDate(String.valueOf(calendarvalue))) {
                    throw new AdderBusinessException("考勤人员档案中人员编码[{0}]，日期{1}不在考勤范围内,不允许导入！请在假勤档案中重新设置员工的考勤方式！", "attend.report.i18n52",
                            new String[]{staff_code, String.valueOf(calendarvalue)});
                }
                Date calendar = DateUtil.StringToDate(String.valueOf(calendarvalue), DateStyle.YYYY_MM_DD);
                if (begindate != null) {
                    if (begindate.getTime() > calendar.getTime()) {
                        begindate = calendar;
                    }
                } else {
                    begindate = calendar;
                }
                if (enddate != null) {
                    if (enddate.getTime() < calendar.getTime()) {
                        enddate = calendar;
                    }
                } else {
                    enddate = calendar;
                }
                //检验是否考勤人员
                if (CalendarCommon.checkActivedDate(attendStaffMap, attendStaff.getStaffCode(), String.valueOf(calendarvalue))) {
                    throw new AdderBusinessException("考勤人员档案中人员编码[{0}]不在考勤范围内", "attend.report.i18n53", staff_code);
                }

                if (stringMapMap != null && stringMapMap.get(attendStaff.getStaffId()) != null) {
                    attendDayRptVO = stringMapMap.get(attendStaff.getStaffId()).get(calendar);
                } else {
                    attendDayRptVO = new AttendDayRptVO();
                    attendDayRptVO.setId((String) IDHelper.nextId());
                    attendDayRptVO.setStaffCode(attendStaff.getStaffCode());
                    attendDayRptVO.setStaffId(attendStaff.getStaffId());
                    attendDayRptVO.setOrgId(attendStaff.getOrgId());
                    attendDayRptVO.setJobId(attendStaff.getStaffjobId());
                    attendDayRptVO.setStaffName(attendStaff.getStaffName());
                    attendDayRptVO.setCalendar(calendar);
                }

                for (int j = 3; j < datalistLen; j++) {
                    String key = keylist.get(j);
                    timeItemVO = (TimeItemVO) timeItemVoName.get(key);
                    if (timeItemVO == null)
                        continue;
                    if (!(ITsFormulaConstant.ITEM_FROM_TYPE_MANUAL == Integer.parseInt(timeItemVO.getIfromflag())))
                        continue;
                    String value = datalist.get(j);
                    Object resultvalue = TsAttendRptUtils.processValue(value, String.valueOf(timeItemVO.getIdatatype()), timeItemVO);
                    String code = timeItemVO.getDbcode();
                    attendDayRptVO.setValue(code, resultvalue);
                    attendDayRptVO.setValue(TsAttendRptUtils.itemCodeToProperty(code),resultvalue);
                    cloumns.add(code);
                }
                insertlist.add(attendDayRptVO);
            }
        } else {
            throw new AdderBusinessException("请添加导入的数据！", "attend.report.i18n54");
        }
        if (insertlist.size() > 0) {
            List<String> ids = FormulaUtils.getPropertyListFromBeanVO(insertlist, "id");
            attendRptCalDao.batchDel4Day(ids);
            attendRptCalDao.batchDel4RptBByPid(ids);
            tsAttentRptDayCalServiceImpl.batchInsertDayRptVos(insertlist, timeItemVOS, tsAttentRptDayCalServiceImpl.getFixItems());
            tsAttentRptDayCalServiceImpl.calculateRpt(begindate, enddate, insertlist, timeItemVOS, extitemVOList, secamid, false);
        }
    }

    public Map<String, Map<Date, AttendDayRptVO>> getRptMap(List<AttendDayRptVO> rptVos) {
        if (CollectionUtils.isEmpty(rptVos))
            return null;
        Map<String, Map<Date, AttendDayRptVO>> result = new HashMap<>();
        Map<Date, AttendDayRptVO> dateRptMap = new HashMap<>();
        for (AttendDayRptVO rpt : rptVos) {
            if (!result.containsKey(rpt.getStaffId())) {
                dateRptMap = new HashMap<>();
                result.put(rpt.getStaffId(), dateRptMap);
            }

            dateRptMap.put(rpt.getCalendar(), rpt);
        }
        return result;
    }

    private void dealMonthImport(List<List<String>> listList, List<TimeItemVO> timeItemVOS, List<TimeItemVO> extitemVOList, Map<String, AttendStaff> attendStaffMap, AttendSchemeVO attendSchemeVO) {
        try {
            //获取数据集合
            List<AttendMonthRptVO> updateList = new ArrayList<>();
            List<AttendMonthRptVO> inserlist = new ArrayList<>();
            Map<String, Object> timeItemVoName = FormulaUtils.getPropertyMapFromBeanVO(timeItemVOS, "name");
            List<String> keylist = null;
            List<String> datalist = null;
            int listListlen = listList.size();
            String year = "";
            String month = "";
            List<String> cloumns = new ArrayList<>();
            if (listListlen > 3) {
                String period = listList.get(1).get(1);
                Date calendarbegin = CalendarCommon.getMonthBegindate(DateUtil.StringToDate(String.valueOf(period), DateStyle.YYYY_MM));
                Date calendarend = CalendarCommon.getMonthEnddate(DateUtil.StringToDate(String.valueOf(period), DateStyle.YYYY_MM));
                SimpleDateFormat sdfs = new SimpleDateFormat(" yyyy-MM-dd");
                String calendarbeginstr = sdfs.format(calendarbegin);
                String calendarendstr = sdfs.format(calendarend);
                String[] ss = period.split("-");
                if (!(ss.length == 2))
                    throw new AdderBusinessException("请输入正确的考勤期间！", "attend.report.i18n55");
                year = ss[0];
                month = ss[1];
                keylist = listList.get(2);
                TimeItemVO timeItemVO = null;
                AttendMonthRptVO attendMonthRptVO = null;
                AttendStaff attendStaff = null;
                List<String> impstaffids = new ArrayList<>();
                for (int i = 3; i < listListlen; i++) {
                    datalist = listList.get(i);
                    if (datalist.size() == 0) {
                        continue;
                    }
                    String staff_code = String.valueOf(datalist.get(0)).replace(".0", "");
                    if ("".equals(String.valueOf(staff_code))) {
                        continue;
                    }
                    attendStaff = attendStaffMap.get(staff_code);
                    if (attendStaff == null) {
                        //throw new AdderBusinessException("考勤人员档案中人员编码[{0}]不在考勤范围内或为“不考勤”,不允许导入！请在假勤档案中重新设置员工的考勤方式！","attend.report.i18n56",staff_code);
                        log.error("考勤人员档案中人员编码[{0}]不在考勤范围内或为“不考勤”,不允许导入！请在假勤档案中重新设置员工的考勤方式！", staff_code);
                        continue;
                    }
                    //检验是否考勤人员
                    if (CalendarCommon.checkActivedDate(attendStaffMap, attendStaff.getStaffCode(), calendarbeginstr) && CalendarCommon.checkActivedDate(attendStaffMap, attendStaff.getStaffCode(), calendarendstr)) {
                        //throw new AdderBusinessException("考勤人员档案中人员编码[{0}]不在考勤范围内,不允许导入！请在假勤档案中重新设置员工的考勤方式","attend.report.i18n57",
                        //        staff_code);
                        log.error("考勤人员档案中人员编码[{0}]不在考勤范围内或为“不考勤”,不允许导入！请在假勤档案中重新设置员工的考勤方式！", staff_code);
                        continue;
                    }

                    impstaffids.add(attendStaff.getStaffId());
                }
                //数据库已存在的数据
                Map<String, AttendMonthRptVO> existMonthRpts = new HashMap<>();
                if (impstaffids.size() == 0) {
                    return;
                }
                //查询已经有的月报
                existMonthRpts = queryLastMonthByCondition(impstaffids.toArray(new String[0]), year, month);
                boolean isnew = false;
                for (int i = 3; i < listListlen; i++) {
                    datalist = listList.get(i);
                    if (datalist.size() == 0) {
                        continue;
                    }
                    String staff_code = String.valueOf(datalist.get(0)).replace(".0", "");
                    if ("".equals(String.valueOf(staff_code))) {
                        continue;
                    }
                    attendStaff = attendStaffMap.get(staff_code);
                    if (attendStaff == null || !impstaffids.contains(attendStaff.getStaffId())) {
                        continue;
                    }
                    AttendMonthRptVO attendMonthRptVOExit = existMonthRpts.get(attendStaff.getStaffId());
                    if (attendMonthRptVOExit != null) {
                        attendMonthRptVO = attendMonthRptVOExit;
                    } else {
                        isnew = true;
                        attendMonthRptVO = new AttendMonthRptVO();
                        attendMonthRptVO.setStaffCode(attendStaff.getStaffCode());
                        attendMonthRptVO.setStaffId(attendStaff.getStaffId());
                        attendMonthRptVO.setOrgId(attendStaff.getOrgId());
                        attendMonthRptVO.setJobId(attendStaff.getStaffjobId());
                        attendMonthRptVO.setStaffName(attendStaff.getStaffName());
                        attendMonthRptVO.setDeptId(attendStaff.getDeptId());
                        attendMonthRptVO.setTsyear(year);
                        attendMonthRptVO.setTsmonth(month);
                        //导入时，增加当前考勤期间开始时间和结束的处理
                        attendMonthRptVO.setBegindate(calendarbegin);
                        attendMonthRptVO.setEnddate(calendarend);
                    }

                    int datalistLen = datalist.size();
                    for (int j = 2; j < datalistLen; j++) {
                        String key = keylist.get(j);
                        timeItemVO = (TimeItemVO) timeItemVoName.get(key);
                        if (timeItemVO == null)
                            continue;
                        if (!(ITsFormulaConstant.ITEM_FROM_TYPE_MANUAL == Integer.parseInt(timeItemVO.getIfromflag())))
                            continue;
                        String value = datalist.get(j);
                        Object resultvalue = TsAttendRptUtils.processValue(value, String.valueOf(timeItemVO.getIdatatype()), timeItemVO);
                        String code = timeItemVO.getDbcode();
                        attendMonthRptVO.setValue(code, resultvalue);
                        attendMonthRptVO.setValue(TsAttendRptUtils.itemCodeToProperty(code),resultvalue);
                        cloumns.add(code);
                    }
                    inserlist.add(attendMonthRptVO);
                }
            } else {
                throw new AdderBusinessException("请添加导入的数据！", "attend.report.i18n54");
            }
            if (inserlist.size() > 0) {
                //查询已经有的月报
                List<String> ids = FormulaUtils.getPropertyListFromBeanVO(inserlist, "id");
                attendRptCalDao.batchDel4Mon(ids);
                attendRptCalDao.batchDel4RptBByPid(ids);
                tsAttentRptMonCalService.batchInsertDayRptVos(inserlist, timeItemVOS, tsAttentRptMonCalService.getFixItems());
                tsAttentRptMonCalService.calculateRpt(year, month, inserlist, timeItemVOS, extitemVOList,attendSchemeVO,false);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
        }
    }

    //endregion
    //region 外部调用
    @Override
    public List<AttendDayRptVO> queryAttendDayRptVOLit(Condition cond, Sort sort) {
        return attendRptdao.querydayByCondition(cond, sort);
    }

    //endregion
    //region 未使用
    @Override
    public List<AttendRptBVO> queryAttendRptbList(Integer repor_type, Condition attcond, Condition childcond) {

        return attendRptdao.queryAttendRptbList(repor_type, attcond, childcond);
    }

    /**
     * 关联方式获取月报子表数据
     */
    public List<AttendRptBVO> queryAttendMonthRptSubList(Condition qcond) {
//    	List<AttendRptBVO> attendRptBVOS = attendRptdao.queryAttendMonthRptSubList(qcond, pageable);
        List<AttendRptBVO> attendRptBVOS = attendRptdao.queryAttendMonthRptSubList(qcond);
        return attendRptBVOS;
    }

    /**
     * 关联方式获取日报子表数据
     */
    public List<AttendRptBVO> queryAttendDayRptSubList(Condition qcond) {
//    	List<AttendRptBVO> attendRptBVOS = attendRptdao.queryAttendDayRptSubList(qcond, pageable);
        List<AttendRptBVO> attendRptBVOS = attendRptdao.queryAttendDayRptSubList(qcond);
        return attendRptBVOS;
    }

    /**
     * 关联方式获取日报子表数据（分页）
     */
    public List<AttendRptBVO> queryAttendDayRptSubList(Condition qcond, Pageable pageable) {
        List<AttendRptBVO> attendRptBVOS = attendRptdao.queryAttendDayRptSubList(qcond, pageable);
        return attendRptBVOS;
    }

    public List<AttendRptBVO> queryAttendRptbListByCommon(Integer reportType, String[] ids) {

        List<AttendRptBVO> attendRptBVOS = new ArrayList<>();
        if (ids.length > 0) {
            int stepNum = 5000;//步长值
            int endPoint;
            for (int startPoint = 0; startPoint < ids.length; startPoint = endPoint) {
                //当剩余数组长度大于5000时一次获取5000个id不足时获取剩下的ID
                endPoint = startPoint + (startPoint + stepNum < ids.length ? stepNum : ids.length - startPoint);
                String[] tempIds = Arrays.copyOfRange(ids, startPoint, endPoint);
                Condition condition = new Condition();
                condition.addExpression("report_type", reportType);
                condition.addExpression("pk_attendrpt", tempIds, "in");
                attendRptBVOS.addAll(genericService.find(AttendRptBVO.class, condition, null));
                startPoint = endPoint;
            }
        }
        return attendRptBVOS;
    }

    @Override
    public List<AttendVieworderRptVO> queryVieworderList(Condition cond, Sort sort) {
        return attendRptdao.queryVieworderList(cond, sort);
    }

    @Override
    public Page<AttendDayRptVO> queryAttendDayRptVO(Condition cond, Pageable pagetable, String Base_Column_List, Sort sort) {
        return attendRptdao.queryTsdaystatList(cond, pagetable, Base_Column_List, sort);
    }

    @Override
    public Page<AttendMonthRptVO> queryAttendMonthRptVO(Condition cond, Pageable pagetable, String Base_Column_List, Sort sort) {
        return attendRptdao.queryTsmonthstatList(cond, pagetable, Base_Column_List, sort);
    }

    @Override
    public List<AttendDayRptVO> queryTsAlldaystatList(Condition cond, String Base_Column_List, Sort sort) {
        return attendRptdao.queryTsAlldaystatList(cond, Base_Column_List, sort);
    }

    @Override
    public List<AttendMonthRptVO> queryTsAllmonthstatList(Condition cond, String Base_Column_List, Sort sort) {
        return attendRptdao.queryTsAllmonthstatList(cond, Base_Column_List, sort);
    }

    //endregion
    //region 薪幅社
    public Object dealDayAndMonthXFSCommon(Integer report_type, Condition qcond) {
        List<AttendMonthRptVO> attendMonthRptVOS = attendRptdao.querymonthByCondition(qcond, null);
        List<AttendRptBVO> childdata = attendRptdao.queryAttendRptbList(1, qcond, null);
        Map<String, List<AttendRptBVO>> childmap = getchildmapBychilddata(childdata);
        for (AttendMonthRptVO apt : attendMonthRptVOS) {
            if (childmap.containsKey(apt.getString("id"))) {
                List<AttendRptBVO> chidVOS = childmap.get(apt.getString("id"));
                for (AttendRptBVO childVO : chidVOS) {
                    apt.setValue(childVO.getPkTimeitem(), childVO.getHournum());
                }
            }
        }
        return attendMonthRptVOS;
    }
    //endregion
    //region DWork调用
    /**
     * Web端日月报查询栏目设置
     *
     * @return
     */

    //endregion

    /**
     * 查询部门日报数据
     *
     * @param cond
     * @param sort
     * @return
     */
    @Override
    public Page<AttendDayRptVO> queryDayRptForDwork(Condition cond, Pageable pageable, Sort sort) {
        return attendRptdao.queryTsPagedaystatListForDwork(cond, pageable, sort);
    }

    /**
     * 查询部门日报数据
     *
     * @param cond
     * @param sort
     * @return
     */
    @Override
    public Page<AttendMonthRptVO> queryMonthForDwork(Condition cond, Pageable pageable, Sort sort) {
        return attendRptdao.queryTsPagemonthstatListForDwork(cond, pageable, sort);
    }

    /**
     * 查询部门日报数据
     *
     * @param cond
     * @param sort
     * @return
     */
    @Override
    public List<AttendDayRptVO> queryDayAllRptForDwork(Condition cond, Sort sort) {
        return attendRptdao.queryTsAlldaystatListForDwork(cond, sort);
    }

    /**
     * 查询部门日报数据
     *
     * @param cond
     * @param sort
     * @return
     */
    @Override
    public List<AttendMonthRptVO> queryMonthAllForDwork(Condition cond, Sort sort) {
        return attendRptdao.queryTsAllmonthstatListForDwork(cond, sort);
    }

    /**
     * 判断是否是部门负责人
     *
     * @return
     */
    @Override
    public Object isPrincipal() {
        boolean isprincipal = false;
        String userId = AppContext.getContext().getUserId();
        String deptid = "";
        CommonSimpleStaff staff = null;
        try {
            staff = simpleStaffCommonHepler.getStaffByUserId(userId);
        } catch (AdderBusinessException e) {
            log.error(e.getMessage(), e);
        }
        if (staff != null) {
            CommonStaffJob staffJob = simpleStaffCommonHepler.loadLastJobByStaffId(staff.getId());
            if (staffJob != null) {
                deptid = staffJob.getDeptid();
                CommonOrg commonOrg = orgCommonHepler.loadDept(deptid);
                if (commonOrg != null) {
                    String principal = commonOrg.getPrincipal();
                    if (staff.getId().equals(principal))
                        isprincipal = true;
                }
            }
        }
        Map<String, Object> resultdata = new HashMap<>();
        resultdata.put("isprincipal", isprincipal);
        resultdata.put("deptid", deptid);
        return resultdata;
    }

    /**
     * 生成 考勤日月报
     *
     * @param report_type = 0 日报 1 月报
     * @param staffid
     * @param date
     * @param year
     * @param month
     */
    public void attendRptCal(String report_type, String staffid, Date date, String year, String month, String schemeId) {

        try {
            //AttendSchemeVO attendSchemeVO = attendSchemeService.queryAttendSchemeById(schemeId);
            AttendSchemeVO attendSchemeVO = genericService.load(AttendSchemeVO.class, schemeId);
            if (attendSchemeVO == null) {
                //考勤方案为空不做计算
                return;
            }
            List<TimeItemVO> extitemVOList = itemService.queryTimeItemsOnlyExt();
            Condition condition = new Condition();
            condition.addExpression("itemtype", report_type);
            condition.addExpression("main_id", attendSchemeVO.getItemSchemeId());
            List<TimeItemVO> itemVOList = itemService.queryItemList(condition, new Sorter(Sort.Direction.ASC, "icomputeseq"));
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

            String[] staffids = new String[]{staffid};
            if ("0".equals(report_type)) {
                tsAttentRptDayCalServiceImpl.calculateRpt(date, date, staffids, itemVOList, extitemVOList, schemeId);
            } else {
                tsAttentRptMonCalService.calculateRpt(year, month, staffids, itemVOList, extitemVOList, schemeId);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 根据方案获取考勤项目方案id
     */
    @Override
    public String getItemmainId(String schemeId) {
        //产品要求不区分初级班和高级版
        AttendSchemeVO attendSchemeVO = attendSchemeService.queryAttendSchemeById(schemeId);
        if (attendSchemeVO == null) {
            throw new AdderBusinessException("不存在考勤方案", "attend.report.i18n58");
        }
        return attendSchemeVO.getItemSchemeId();
    }

    public AttendSchemeVO getAttendSchemeVO(String schemeId, String deptid, boolean isIncludeSub, boolean powerFlag) {
        AttendSchemeVO attendSchemeVO;
        if (StringUtils.isBlank(schemeId)) {
            attendSchemeVO = itimeCommonService.queryAttendSchemeByOrgID(deptid);
            attendSchemeVO.setOrgs(Arrays.asList(deptid));
        } else {
            List<String> orglist = CalendarCommon.getListids(deptid);
            attendSchemeVO = getAttendSchemeVO(schemeId, orglist, isIncludeSub, powerFlag);
        }

        return attendSchemeVO;
    }

    public AttendSchemeVO getAttendSchemeVOWeb(String schemeId, String deptid, boolean isIncludeSub, boolean powerFlag) {
        AttendSchemeVO attendSchemeVO = new AttendSchemeVO();
        if (StringUtils.isBlank(schemeId)) {
            CommonOrg org = orgCommonHepler.loadOrgAndDept(deptid);
            if (org != null) {
                log.info("######## dealDayAndMonthCommon #### 上级组织id:" + org.getOrgid());
                attendSchemeVO = itimeCommonService.queryAttendSchemeByOrgID(org.getOrgid());
            } else {
                attendSchemeVO = itimeCommonService.queryAttendSchemeByOrgID(deptid);
            }
            if (attendSchemeVO != null) {
                attendSchemeVO.setOrgs(Arrays.asList(deptid));
            }
        } else {
            List<String> orglist = CalendarCommon.getListids(deptid);
            attendSchemeVO = getAttendSchemeVO(schemeId, orglist, isIncludeSub, powerFlag);
        }

        return attendSchemeVO;
    }

    @Override
    public Map<String, Object> queryAttendanceForDept(String staffid, String deptid, Date begindate, Date enddate) {
        Map<String, Object> result = new HashMap<>();
        AttendanceDayRptVO dayRptVO = new AttendanceDayRptVO();
        Condition cond = new Condition();
        cond.addExpression("staff.dept_id", deptid);
        cond.addExpression("day.calendar", begindate, ">=");
        cond.addExpression("day.calendar", enddate, "<=");
        List<AttendanceDayRptVO> attendanceDayRptVOList = attendRptdao.queryAttendanceForDept(cond);
        if (attendanceDayRptVOList.size() > 0) {
            BigDecimal sumAllactualworkhours = BigDecimal.ZERO;
            BigDecimal sumAllworkhours = BigDecimal.ZERO;
            BigDecimal sumAllworkdays = BigDecimal.ZERO;
            Integer sumAllnormal = 0;
            int i = 1;
            int index = 1;
            for (AttendanceDayRptVO attendanceDayRptVO : attendanceDayRptVOList) {
                sumAllactualworkhours = sumAllactualworkhours.add(attendanceDayRptVO.getSumactualworkhours());
                sumAllworkhours = sumAllworkhours.add(attendanceDayRptVO.getSumworkhours());
                sumAllworkdays = sumAllworkdays.add(attendanceDayRptVO.getSumworkdays());
                sumAllnormal += attendanceDayRptVO.getSumnormal();
                if (staffid.equals(attendanceDayRptVO.getStaffId())) {
                    dayRptVO = attendanceDayRptVO;
                    index = i;
                }
                i++;
            }
            //日均工时
            //个人
            if (dayRptVO.getSumactualworkhours() == null) {
                dayRptVO.setSumactualworkhours(BigDecimal.ZERO);
            }
            dayRptVO.setPersonPercent(dayRptVO.getSumactualworkhours().divide(dayRptVO.getSumworkdays(), 1));
            dayRptVO.setDeptPercent(sumAllactualworkhours.divide(sumAllworkdays, 1));
            //出勤率
            if (dayRptVO.getAttendance() == null) {
                dayRptVO.setAttendance(BigDecimal.ZERO);
            }
            dayRptVO.setAttendance(dayRptVO.getAttendance().setScale(2, BigDecimal.ROUND_HALF_UP));
            if (sumAllworkhours != BigDecimal.ZERO) {
                dayRptVO.setDeptattendance(sumAllactualworkhours.divide(sumAllworkhours, 1));
            }

            //评价结果
            double avg = ((double) index) / attendanceDayRptVOList.size();
            if (avg <= 0.2) {
                dayRptVO.setEvaluate("优秀");
            } else if (avg < 0.9) {
                dayRptVO.setEvaluate("正常");
            } else {
                dayRptVO.setEvaluate("需关注");
            }
        }
        result.put("staffId", dayRptVO.getStaffId());
        result.put("sumactualworkdays", dayRptVO.getSumactualworkdays());
        result.put("sumactualworkhours", dayRptVO.getSumactualworkhours());
        result.put("sumworkdays", dayRptVO.getSumworkdays());
        result.put("sumworkhours", dayRptVO.getSumworkhours());
        result.put("personPercent", dayRptVO.getPersonPercent());
        result.put("deptPercent", dayRptVO.getDeptPercent());
        result.put("attendance", dayRptVO.getDeptattendance());
        result.put("deptattendance", dayRptVO.getDeptattendance());
        result.put("sumnormal", dayRptVO.getSumnormal());
        result.put("evaluate", dayRptVO.getEvaluate());
        return result;
    }

    @Override
    public Map<String, BigDecimal> queryAttendCtieRptVO() {
        Map<String, BigDecimal> result = new HashMap<>();
        String userid = AppContext.getContext().getUserId();
        CommonSimpleStaff staff = simpleStaffCommonHepler.getStaffByUserId(userid);
        String deptid = staff.getDeptId();
        Date date = new Date();
        Integer year = DateUtil.getYear(date);
        Integer month = DateUtil.getMonth(date);
        List<Integer> months = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            months.add(month - i);
            result.put(String.valueOf(month - i), BigDecimal.ZERO.setScale(2));
        }
        if (StringUtils.isNotBlank(deptid)) {
            Condition cond = new Condition();
            cond.addExpression("staff.dept_id", deptid);
            cond.addExpression("month.tsyear", year);
            cond.addExpression("month.tsmonth", months, "in");
            List<AttendanceDayRptVO> monthRptVOS = attendRptdao.queryAttendanceCTForDept(cond);
            for (AttendanceDayRptVO attendanceDayRptVO : monthRptVOS) {
                result.put(attendanceDayRptVO.getTsmonth(), attendanceDayRptVO.getAvg().setScale(2, BigDecimal.ROUND_HALF_UP));
            }
        }
        return result;
    }


    @Override
    public AttendSchemeVO getAttendSchemeVO(String schemeId, List<String> orglist, boolean isIncludeSub, boolean powerFlag) {
        log.debug("####TM getAttendSchemeVO-計算获取人员有权限的假勤方案并处理部门的交集_Start..");
        AttendSchemeVO attendSchemeVO = iAttendSchemeService.queryAttendSchemeByIdForPower(schemeId, IServceCodeConstant.ATTEND_STATISTICS, 4, powerFlag);
        if (orglist != null && orglist.size() > 0) {
            List<String> orgsnew = new ArrayList<>();
            List<String> childOrgs = orgCommonHepler.getOrgAndChildIds(orglist, "2", isIncludeSub);
            List<String> orgold = attendSchemeVO.getOrgs();
            if (childOrgs.size() > 0) {
                for (String id : childOrgs) {
                    if (orgold.contains(id)) {
                        orgsnew.add(id);
                    }
                }
                attendSchemeVO.setOrgs(orgsnew);
            }
            log.debug(String.format("####TM getAttendSchemeVO-假勤方案的部门信息:%s,参数信息:%s", JSONObject.toJSONString(orgold), JSONObject.toJSONString(childOrgs)));
        }
        log.debug("####TM getAttendSchemeVO-計算获取人员有权限的假勤方案并处理部门的交集_end:" + JSONObject.toJSONString(attendSchemeVO.getOrgs()));
        return attendSchemeVO;
    }

    @Override
    public List<AttendMonthRptVO> getAttendMonthRptVOS(Condition cond, Sort sort) {
        return attendRptdao.querymonthByCondition(cond, sort);
    }


    /***
     * 查询月报数据(FOR薪酬) Map<staffId,Map<CorpId,Map<itemId,value>>>
     * @param year 年
     * @param month 月
     * @param staffIds 人员信息
     * @return 月报数据(FOR薪酬)
     */
    @Override
    public Map<String, Map<String, Map<String, Object>>> queryMonthRptForSalary(String year, String month, List<String> staffIds) {
        if (StringUtils.isEmpty(year) || StringUtils.isEmpty(month) || CollectionUtils.isEmpty(staffIds)) {
            throw new AdderBusinessException("参数异常!", "attend.report.i18n1");
        }
        Map<String, Map<String, Map<String, Object>>> mapResult = new HashMap<>();
        Condition condition = new Condition();
        condition.addExpression("month.tsyear", year);
        condition.addExpression("month.tsmonth", month);
        condition.addExpression("month.staff_id", staffIds, "in");
        //查询月报数据
        List<AttendMonthRptVO> list = queryMonthAllForDwork(condition, null);
        if (CollectionUtils.isEmpty(list)) return mapResult;
        Map<String, String> mapItemInfo = getItemMap();
        for (AttendMonthRptVO monthVO : list) {
            Map<String, Object> mapMonthData = new HashMap<>();
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(monthVO));
            for (String key : jsonObject.keySet()) {
                mapMonthData.put(key, jsonObject.get(key));
            }
            //扩展项
            Map<String, Object> tempMap = monthVO.tempData();
            if (MapUtils.isNotEmpty(tempMap)) {
                for (Map.Entry<String, Object> entry : tempMap.entrySet()) {
                    if (!mapItemInfo.containsKey(entry.getKey())) continue;
                    mapMonthData.put(mapItemInfo.get(entry.getKey()), entry.getValue());
                }
            }
            //Map<staffId,Map<CorpId,Map<itemId,value>>>
            processResult(mapResult, monthVO, mapMonthData);
        }
        return mapResult;
    }

    @Override
    public Map<String, Map<String, Map<String, Object>>> queryMonthDataForSalary(String year, String month, List<String> staffIds, int type) {
        if (type == 0) return queryMonthRptForSalary(year, month, staffIds);
        Map<String, Map<String, Map<String, Object>>> mapResult = new HashMap<>();
        Condition condition = new Condition();
        condition.addExpression("tsyear", year);
        condition.addExpression("tsmonth", month);
        condition.addExpression("staff_id", staffIds, "in");
        List<AttendMonthRptVO> list = attendRptdao.queryTsAllmonthstatList(condition, null, null);
        if (CollectionUtils.isEmpty(list)) return mapResult;
        List<String> listPKs = FormulaUtils.getPropertyListFromBeanVO(list, "id");
        Map<String, String> mapBusDataType = getBusDataTypeMap(type);
        Map<String, Map<String, Object>> mapSubRpt = getSubRptMap(listPKs, mapBusDataType);
        for (AttendMonthRptVO monthVO : list) {
            Map<String, Object> mapMonthData = new HashMap<>();
            //报表子表
            if (MapUtils.isNotEmpty(mapSubRpt) && mapSubRpt.containsKey(monthVO.getId())) {
                Map<String, Object> mapCurSubRpt = mapSubRpt.get(monthVO.getId());
                if (MapUtils.isNotEmpty(mapCurSubRpt)) mapMonthData.putAll(mapCurSubRpt);
            }
            //Map<staffId,Map<CorpId,Map<itemId,value>>>
            if (MapUtils.isNotEmpty(mapMonthData)) processResult(mapResult, monthVO, mapMonthData);
        }
        return mapResult;
    }

    private void processResult(Map<String, Map<String, Map<String, Object>>> mapResult, AttendMonthRptVO monthVO, Map<String, Object> mapMonthData) {
        //Map<staffId,Map<CorpId,Map<itemId,value>>>
        if (mapResult.containsKey(monthVO.getStaffId())) {
            Map<String, Map<String, Object>> mapOrgData = mapResult.get(monthVO.getStaffId());
            if (mapOrgData.containsKey(monthVO.getOrgId())) {
                mapOrgData.put(monthVO.getOrgId(), mapMonthData);
                mapResult.put(monthVO.getStaffId(), mapOrgData);
            } else {
                Map<String, Map<String, Object>> mapOrgDataNew = new HashMap<>();
                mapOrgDataNew.put(monthVO.getOrgId(), mapMonthData);
                mapResult.put(monthVO.getStaffId(), mapOrgDataNew);
            }
        } else {
            Map<String, Map<String, Object>> mapOrgData = new HashMap<>();
            mapOrgData.put(monthVO.getOrgId(), mapMonthData);
            mapResult.put(monthVO.getStaffId(), mapOrgData);
        }
    }

    private Map<String, String> getItemMap() {
        Map<String, String> mapData = new HashMap<>();
        List<TimeItemVO> list = itemService.queryItems(String.format("%s0000000001", AppContext.getContext().getScope()), "1");
        if (CollectionUtils.isEmpty(list)) return mapData;
        for (TimeItemVO itemVO : list) {
            mapData.put(StrConversionUtils.lineToHump(itemVO.getDbcode()), itemVO.getDbcode());
        }
        //list.forEach(t->mapData.put(StrConversionUtils.lineToHump(t.getDbcode()),t.getDbcode()));
        return mapData;
    }

    /***
     * 查询租户下业务类型map
     * 假别和出差类别的id和refId
     * @param type 数据类型：0-月报；1-请假；2-加班；3-出差
     * @return Map<String, String>
     */
    private Map<String, String> getBusDataTypeMap(int type) {
        if (type == 2) {
            Map<String, String> mapData = new HashMap<>();
            mapData.put("ogt91cyx100000jsbaaa", "ogt91cyx100000jsbaaa");
            mapData.put("ogt91cyx10000000baaa", "ogt91cyx10000000baaa");
            mapData.put("ogt91cyx10000000babd", "ogt91cyx10000000babd");
            mapData.put("ogt91cyx10000000babc", "ogt91cyx10000000babc");
            mapData.put("ogt91cyx100000jsbabc", "ogt91cyx100000jsbabc");
            mapData.put("ogt91cyx100000jsbabd", "ogt91cyx100000jsbabd");
            return mapData;
        }
        Condition condition = new Condition();
        condition.addExpression("enablestate", 1);
        return type == 1 ? leaveTypeService.getRefMap(condition) : tripTypeService.getRefMap(condition);
    }

    private Map<String, Map<String, Object>> getSubRptMap(List<String> listPKs, Map<String, String> mapBusDataType) {
        Condition condition = new Condition();
        condition.addExpression("report_type", 1);
        condition.addExpression("pk_attendrpt", listPKs, "in");
        List<AttendRptBVO> list = genericService.find(AttendRptBVO.class, condition, null);
        Map<String, Map<String, Object>> mapData = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) return mapData;
        for (AttendRptBVO vo : list) {
            if (!mapBusDataType.containsKey(vo.getPkTimeitem())) continue;
            if (mapData.containsKey(vo.getPkAttendrpt())) {
                mapData.get(vo.getPkAttendrpt()).put(mapBusDataType.get(vo.getPkTimeitem()), vo.getHournum());
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put(mapBusDataType.get(vo.getPkTimeitem()), vo.getHournum());
                mapData.put(vo.getPkAttendrpt(), map);
            }
        }
        return mapData;
    }

    /***
     * 查询月报
     * @param schemeId
     * @param year
     * @param month
     * @param deptId
     * @param jobId
     * @param isIncludeSub
     * @param staffName
     * @param pageable
     * @return
     */
    @Override
    public Object queryMonthRpt(String schemeId, String year, String month, String deptId, String jobId, boolean isIncludeSub, String staffName, Pageable pageable) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("######## dealDayAndMonthCommon getAttendSchemeVOWeb");
        AttendSchemeVO attendSchemeVO = getAttendSchemeVOWeb(schemeId, deptId, isIncludeSub, true);
        stopWatch.stop();
        if (attendSchemeVO == null) {
            throw new AdderBusinessException("没有对应的假勤方案！", "attend.report.i18n59");
        }
        stopWatch.start("######## dealDayAndMonthCommon queryVieworderMapByScheme");
        Map<String, Object> titleResult = getTitleResult(attendSchemeVO, 1);
        String columns = String.valueOf(titleResult.get("columns"));
        stopWatch.stop();
        stopWatch.start("######## dealDayAndMonthCommon deal");
        Map<String, Object> resultData = new HashMap<>();
        Object monthData = null;
        if (CollectionUtils.isNotEmpty(attendSchemeVO.getOrgs())) {
            monthData = queryMonthRptData(year, month, attendSchemeVO.getOrgs(), jobId, staffName, pageable, columns);
        } else {
            monthData = getBlankData(pageable);
        }
        resultData.put("data", monthData);
        resultData.put("title", titleResult.get("titleList"));
        resultData.put("itemdata", titleResult.get("itemJson"));
        stopWatch.stop();
        log.debug(stopWatch.prettyPrint());
        return resultData;
    }

    private Object queryMonthRptData(String year, String month, List<String> deptIds, String jobId, String staffName, Pageable pageable, String columns) {
        Condition monthCondition = new Condition();
        monthCondition.addExpression("tsyear", year);
        monthCondition.addExpression("tsmonth", month);
        monthCondition.addExpression("dept_id", deptIds, Operator.IN);
        List<AttendStaff> attendStaffList = queryAttendStaff(jobId, staffName);
        if ((StringUtils.isNotBlank(jobId) || StringUtils.isNotBlank(staffName)) && CollectionUtils.isEmpty(attendStaffList)) {
            return getBlankData(pageable);
        }
        //如果有职务或人员信息，先根据职务和人员姓名查找人员数据，再查询月报数据，最后翻译
        if (CollectionUtils.isNotEmpty(attendStaffList)) {
            List<String> idList = com.yonyou.hrcloud.tcommon.utils.FormulaUtils.getPropertyListFromBeanVO(attendStaffList, "staffId");
            monthCondition.addExpression("staff_id", idList, Operator.IN);
        }
        return dealMonthOnly(monthCondition, pageable, columns, attendStaffList);
    }

    //月报处理
    private Object dealMonthOnly(Condition qcond, Pageable pageable, String columns, List<AttendStaff> attendStaffList) {
        Page<AttendMonthRptVO> attendMonthRptVOPages = getAttendmonthRptByOnly(qcond, pageable, columns);
        if (attendMonthRptVOPages == null || attendMonthRptVOPages.getTotalPages() == 0) return getBlankData(pageable);
        List<String> pkAttendRpt = new ArrayList<>();
        List<String> listDeptIds = new ArrayList<>();//部门id
        List<String> listStaffIds = new ArrayList<>();//人员id
        boolean loadStaff = CollectionUtils.isEmpty(attendStaffList);
        for (AttendMonthRptVO attendMonthRptVO : attendMonthRptVOPages) {
            pkAttendRpt.add(attendMonthRptVO.getId());
            if (StringUtils.isNotEmpty(attendMonthRptVO.getDeptId()) && !listDeptIds.contains(attendMonthRptVO.getDeptId())) {
                listDeptIds.add(attendMonthRptVO.getDeptId());
            }
            if (StringUtils.isNotEmpty(attendMonthRptVO.getOrgId()) && !listDeptIds.contains(attendMonthRptVO.getOrgId())) {
                listDeptIds.add(attendMonthRptVO.getOrgId());
            }
            if (loadStaff && StringUtils.isNotEmpty(attendMonthRptVO.getStaffId()) && !listStaffIds.contains(attendMonthRptVO.getStaffId())) {
                listStaffIds.add(attendMonthRptVO.getStaffId());
            }
        }
        if (loadStaff && CollectionUtils.isEmpty(attendStaffList) && CollectionUtils.isNotEmpty(listStaffIds)) {
            Condition cond = new Condition();
            cond.addExpression("staff_id", listStaffIds, Operator.IN);
            Sorter sorter = new Sorter(Sort.Direction.ASC, "staff_id");
            sorter = sorter.and(new Sorter(Sort.Direction.ASC, "begindate"));
            attendStaffList = genericService.find(AttendStaff.class, cond, sorter);
        }
        if (CollectionUtils.isEmpty(attendStaffList)) {
            return getBlankData(pageable);
        }


        //当人员信息查询后没有员工名字信息时，用假勤档案查询的结果赋值
        Map<String,String> attendStaffNameMap = new HashMap<>();
        for (AttendStaff staff : attendStaffList) {
            if (!listStaffIds.contains(staff.getStaffId())) {
                listStaffIds.add(staff.getStaffId());
            }
            attendStaffNameMap.put(staff.getStaffId(), staff.getStaffName());
        }

        List<AttendRptBVO> childData = queryAttendRptbListByCommon(1, pkAttendRpt.toArray(new String[0]));
        Map<String, List<AttendRptBVO>> childMap = getchildmapBychilddata(childData);
        Map<String, String> mapDeptInfo = TranslatorToMapUtils.getDeptMap(listDeptIds);
        // 取staffcode、staffname，该函数可能会导致无法获取员工姓名，故注释
//        Map<String, String> mapStaffCodeInfo = TranslatorToMapUtils.getFileNameMap(listStaffIds, "code");
//        Map<String, String> mapStaffNameInfo = TranslatorToMapUtils.getFileNameMap(listStaffIds, "name");

        // 直接获取 CommonSimpleStaff 避免可能的错误
        log.error("----------------start to get CommonSimpleStaff-------------------");
        Map<String, CommonSimpleStaff> staffList = TranslatorToMapUtils.getStaff(listStaffIds);
        log.error("------------staffList is shown as following:-------------\n"+JSONObject.toJSONString(staffList));

        for (AttendMonthRptVO apt : attendMonthRptVOPages) {
            if (staffList.containsKey(apt.getStaffId())) {
//                apt.setStaffCode(mapStaffCodeInfo.get(apt.getStaffId()));
//                apt.setStaffName(mapStaffNameInfo.get(apt.getStaffId()));
                CommonSimpleStaff staff = staffList.get(apt.getStaffId());
                log.error("------------staff: id="+staff.getId()+" code="+staff.getCode()+" name="+staff.getName()+"\n");
                apt.setStaffCode(staff.getCode());
                apt.setStaffName(staff.getName());
            }

            //当人员信息查询后没有员工名字信息时，用假勤档案查询的结果赋值,避免人员姓名为空
            if (StringUtils.isEmpty(apt.getStaffName())) {
                //用getOrDefault是为了防止map中该key值不存在
                apt.setStaffName(attendStaffNameMap.get(apt.getStaffId()));
            }

            //部门名称
            if (mapDeptInfo.containsKey(apt.getDeptId())) {
                apt.setDeptName(mapDeptInfo.get(apt.getDeptId()));
            }
            if (mapDeptInfo.containsKey(apt.getOrgId())) {
                apt.setOrgName(mapDeptInfo.get(apt.getOrgId()));
            }
            if (childMap.containsKey(apt.getString("id"))) {
                List<AttendRptBVO> chidVOS = childMap.get(apt.getString("id"));
                for (AttendRptBVO childVO : chidVOS) {
                    apt.setValue(childVO.getPkTimeitem(), childVO.getHournum());
                }
            }
        }
        return attendMonthRptVOPages;
    }

    private Map<String, Object> getBlankData(Pageable pageable) {
        Map<String, Object> data = new HashMap<>();
        data.put("content", new JSONArray());
        data.put("pageable", pageable);
        data.put("first", 0);
        data.put("last", 0);
        data.put("number", 0);
        data.put("numberOfElements", 0);
        data.put("size", 0);
        data.put("totalElements", 0);
        data.put("totalPages", 0);
        return data;
    }

    /***
     * 根据职务和姓名编码查询假勤档案
     * @param jobId
     * @param staffName
     * @return
     */
    private List<AttendStaff> queryAttendStaff(String jobId, String staffName) {
        Condition cond = new Condition();
        if (StringUtils.isNotBlank(jobId)) {
            cond.addExpression("job_id", jobId.trim());
        }
        if (StringUtils.isNotBlank(staffName)) {
            ChainLogicExpression cle = new ChainLogicExpression(true,
                    new ValueExpression("staff_code", staffName, Operator.LIKEANY),
                    new ValueExpression("staff_name", staffName, Operator.LIKEANY));
            cond.addExpressions(cle);
        }
        if (CollectionUtils.isEmpty(cond.getExpressions())) return null;
        return genericService.find(AttendStaff.class, cond, null);
    }


    /***
     * 获取栏目数据
     * @param attendSchemeVO
     * @param reportType
     * @return
     */
    private Map<String, Object> getTitleResult(AttendSchemeVO attendSchemeVO, int reportType) {
        Map<String, Object> data = queryViewOrderMapByScheme(attendSchemeVO, reportType);
        List<AttendVieworderRptVO> showOrderList = new ArrayList<>();
        if (MapUtils.isNotEmpty(data)) {
            showOrderList = (List<AttendVieworderRptVO>) data.get("showorderlist");
        }
        if (CollectionUtils.isEmpty(showOrderList)) {
            throw new AdderBusinessException("请至少选择一个栏目！", "attend.report.i18n46");
        }
        return getTitleData(reportType, showOrderList);
    }
}
