package com.kingdee.eas.custom.projectbonus.app;

import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemCollection;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.custom.orgunitEx.ProjectType;
import com.kingdee.eas.custom.projectbonus.*;
import com.kingdee.eas.custom.projectbonus.bizEnum.BusDepProjectStateEnum;
import com.kingdee.eas.custom.projectbonus.bizEnum.CycleStateEnum;
import com.kingdee.eas.hr.org.JobGradeInfo;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.base.syssetting.BaseItemException;
import com.kingdee.shr.compensation.exception.CmpEASDbException;
import com.kingdee.util.DateTimeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.kingdee.bos.*;
import com.kingdee.bos.metadata.entity.SelectorItemCollection;
import com.kingdee.eas.common.EASBizException;

import java.lang.String;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.util.Date;

public class BonusCycleBusDepProjectControllerBean extends AbstractBonusCycleBusDepProjectControllerBean {
    private static Logger logger =
            Logger.getLogger(BonusCycleBusDepProjectControllerBean.class);
    //查询列
    private final static SelectorItemCollection sic = new SelectorItemCollection();
    //更新列
    private final static SelectorItemCollection updateSic = new SelectorItemCollection();
    //根组织id
    private final String ROOTID = "00000000-0000-0000-0000-000000000000CCE7AED4";

    static {
        sic.add("state");
        sic.add("project.name");
        sic.add("busDep.name");
        sic.add("bonusAmount");
        sic.add("principal");
        sic.add("parent.state");
        sic.add("parent.state");
        updateSic.add("state");
    }


    /**
     * 启用
     *
     * @param ctx
     * @param billId 单据id
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _enable(Context ctx,
                           String billId) throws BOSException, EASBizException {
        //super._enable(ctx, billId);
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        //奖金分包金额
        PersonInfo principal = info.getPrincipal();
        if (BusDepProjectStateEnum.INITIALIZATION.equals(state) || BusDepProjectStateEnum.DISABLE.equals(state)) {
            //状态等于初始化 或 禁用
            if (principal == null) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"事业部负责人不能为空！"});
            }
            info.setState(BusDepProjectStateEnum.ENABLE);
            try {
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.SUBMITED.equals(state)
                || BusDepProjectStateEnum.RECHECK.equals(state)
                || BusDepProjectStateEnum.SUBMITCALCULATED.equals(state)) {
            //状态等于已提交
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行启用操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 禁用
     *
     * @param ctx
     * @param billId 单据id
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _disable(Context ctx,
                            String billId) throws EASBizException {
        try {
            if (StringUtils.isEmpty(billId)) {
                logger.error("单据id不能为空！");
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
            }
            BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
            CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
            if (CycleStateEnum.LOCK.equals(cycleState)) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
            }
            BusDepProjectStateEnum state = info.getState();
            if (!BusDepProjectStateEnum.DISABLE.equals(state)) {
                info.setState(BusDepProjectStateEnum.DISABLE);
                try {
                    updatePartial(ctx, info, updateSic);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error(e.getMessage());
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
                }
            }
        } catch (BOSException e) {
            e.printStackTrace();
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
        }
    }

    /**
     * 提交
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _submit(Context ctx, String billId) throws BOSException, EASBizException {
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        SelectorItemCollection querySic = new SelectorItemCollection();
        querySic.add("state");
        querySic.add("project.name");
        querySic.add("busDep.name");
        querySic.add("principal");
        querySic.add("parent.state");
        querySic.add("AssPersonnelDetail.person.id");//人员id
        querySic.add("AssPersonnelDetail.person.name");//姓名
        querySic.add("AssPersonnelDetail.functionCoefficient");//职能系数
        querySic.add("AssPersonnelDetail.energyInputCoeff");//精力投入系数
        querySic.add("AssPersonnelDetail.bonusDueDate");//奖金期限截止日期
        querySic.add("AssPersonnelDetail.bonusStartingDate");//奖金期限起算日期
        querySic.add("AssPersonnelDetail.grade");//职等
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), querySic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        if (BusDepProjectStateEnum.ENABLE.equals(state)) {
            //分配人员明细
            BonusCycleBusDepProjectAssPersonnelDetailCollection assPersonnelDetailCols = info.getAssPersonnelDetail();
            for (int i = 0; assPersonnelDetailCols != null && i < assPersonnelDetailCols.size(); i++) {
                BonusCycleBusDepProjectAssPersonnelDetailInfo personnelDetailInfo = assPersonnelDetailCols.get(i);
                PersonInfo person = personnelDetailInfo.getPerson();
                if (person == null) {
                    logger.error("分配人员不能为空!");
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"分配人员不能为空!"});
                }
                //姓名
                String personName = personnelDetailInfo.getPerson().getName();
                //职等
                JobGradeInfo grade = personnelDetailInfo.getGrade();
                if (grade == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的职等不能为空！"});
                }
                //职能系数
                BigDecimal functionCoefficient = personnelDetailInfo.getFunctionCoefficient();
                if (functionCoefficient == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的职能系数不能为空！"});
                }
                //精力投入系数
                BigDecimal energyInputCoeff = personnelDetailInfo.getEnergyInputCoeff();
                if (energyInputCoeff == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的精力投入系数不能为空！"});
                }
                //奖金期限起算日期
                Date bonusStartingDate = personnelDetailInfo.getBonusStartingDate();
                if (bonusStartingDate == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的奖金期限起算日期不能为空！"});
                }
                //奖金期限截止日期
                Date bonusDueDate = personnelDetailInfo.getBonusDueDate();
                if (bonusDueDate == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的奖金期限截止日期不能为空！"});
                }
                if (bonusStartingDate.compareTo(bonusDueDate) >= 0) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]奖金期限截止日期 不得早于或等于 奖金期限起算日期"});
                }
                //出勤率 = (奖金期限截止日期-奖金期限起算日期)/180
                double day = DateTimeUtils.dateDiff(bonusStartingDate, bonusDueDate) / 86400000.0 / 180.0 * 100;
                if (day <= 0) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的出勤率[" + day + "]不能小于等于0!"});
                }
            }
            //状态等于启用
            info.setState(BusDepProjectStateEnum.SUBMITED);
            try {
                //计算
                //calculate(ctx, billId);
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, e, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                || BusDepProjectStateEnum.RECHECK.equals(state)
                || BusDepProjectStateEnum.SUBMITCALCULATED.equals(state)) {
            //状态等于禁用 或 初始化 或 已复核 或 已提交计算
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行提交操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 撤回
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _withdraw(Context ctx, String billId) throws EASBizException {
        try {
            if (StringUtils.isEmpty(billId)) {
                logger.error("单据id不能为空！");
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
            }
            BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
            CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
            if (CycleStateEnum.LOCK.equals(cycleState)) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
            }
            BusDepProjectStateEnum state = info.getState();
            String alias = state.getAlias();
            if (BusDepProjectStateEnum.SUBMITED.equals(state)) {
                //状态等于已提交
                info.setState(BusDepProjectStateEnum.ENABLE);
                try {
                    updatePartial(ctx, info, updateSic);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
                }
            } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                    || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                    || BusDepProjectStateEnum.RECHECK.equals(state)
                    || BusDepProjectStateEnum.SUBMITCALCULATED.equals(state)) {
                //状态等于禁用 或 初始化 或 已复核 或 已提交计算
                StringBuilder errorMsg = new StringBuilder();
                errorMsg.append(getBusDepMsg(info));
                errorMsg.append(alias).append("，不允许执行撤回操作！");
                logger.error(errorMsg.toString());
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
            }
        } catch (BOSException e) {
            e.printStackTrace();
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
        }
    }

    /**
     * 计算个人奖金额
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _calculate(Context ctx, String billId) throws EASBizException {
        try {
            if (StringUtils.isEmpty(billId)) {
                logger.error("单据id不能为空！");
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
            }
            SelectorItemCollection depSic = new SelectorItemCollection();
            depSic.add("*");
            depSic.add("project.name");
            depSic.add("busDep.name");
            depSic.add("AssPersonnelDetail.person.name");
            depSic.add("AssPersonnelDetail.grade.coefficient");
            depSic.add("AssPersonnelDetail.*");
            depSic.add("parent.state");
            SelectorItemCollection updateDetailSic = new SelectorItemCollection();
            updateDetailSic.add("attendanceRate");
            updateDetailSic.add("assessmentCoeff");
            updateDetailSic.add("cumulative");
            updateDetailSic.add("bonusProportion");
            updateDetailSic.add("indivBonusAmount");
            updateDetailSic.add("approvalAmount");
            updateDetailSic.add("opinionAmount");
            //事业部项目
            BonusCycleBusDepProjectInfo info = (BonusCycleBusDepProjectInfo) getValue(ctx, new ObjectUuidPK(billId), depSic);
            CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
            if (CycleStateEnum.LOCK.equals(cycleState)) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
            }
            BusDepProjectStateEnum state = info.getState();
            if (!BusDepProjectStateEnum.SUBMITED.equals(state)) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{getBusDepMsg(info) + "非已提交状态，不允许执行计算操作！"});
            }
            //奖金分包金额
            BigDecimal bonusAmount = info.getBonusAmount();
            if (bonusAmount == null) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{getBusDepMsg(info) + "的奖金分包金额为空！"});
            }
            if (bonusAmount.compareTo(BigDecimal.ZERO) < 0) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{getBusDepMsg(info) + "的奖金分包金额小于0，无法执行计算操作！"});
            }
            //分配人员明细
            BonusCycleBusDepProjectAssPersonnelDetailCollection assPersonnelDetailCols = info.getAssPersonnelDetail();
            IBonusCycleBusDepProjectAssPersonnelDetail iBonusCycleBusDepProjectAssPersonnelDetail = BonusCycleBusDepProjectAssPersonnelDetailFactory.getLocalInstance(ctx);
            //同事业部下（职能系数 * 出勤率 * 精力投入系数 * 职级系数 * 个人考核系数）之和
            BigDecimal cumulativeSum = BigDecimal.ZERO;
            //剩余同事业部下（职能系数 * 出勤率 * 精力投入系数 * 职级系数 * 个人考核系数）之和
            BigDecimal cumulativeSurplus = BigDecimal.ZERO;
            //剩余奖金分包金额
            BigDecimal bonusAmountSurplus = BigDecimal.ZERO;
            for (int i = 0; i < assPersonnelDetailCols.size(); i++) {
                BonusCycleBusDepProjectAssPersonnelDetailInfo detailInfo = assPersonnelDetailCols.get(i);
                //姓名
                String personName = detailInfo.getPerson().getName();
                //奖金期限起算日期
                Date bonusStartingDate = detailInfo.getBonusStartingDate();
                if (bonusStartingDate == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的奖金期限起算日期为空！"});
                }
                //奖金期限截止日期
                Date bonusDueDate = detailInfo.getBonusDueDate();
                if (bonusDueDate == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的奖金期限截止日期为空！"});
                }
                if (bonusStartingDate.compareTo(bonusDueDate) >= 0) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"奖金期限截止日期 不得早于或等于 奖金期限起算日期"});
                }
                //出勤率 = (奖金期限截止日期-奖金期限起算日期)/180
                double day = DateTimeUtils.dateDiff(bonusStartingDate, bonusDueDate) / 86400000.0 / 180.0 * 100;
                if (day <= 0) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的出勤率[" + day + "]不能小于等于0!"});
                }
                BigDecimal attendanceRate = new BigDecimal(String.valueOf(day)).setScale(0, RoundingMode.HALF_UP);
                detailInfo.setAttendanceRate(attendanceRate);
                //Q1绩效系数
                BigDecimal performanceCoeffQ1 = detailInfo.getPerformanceCoeffQ1();
                if (performanceCoeffQ1 == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的Q1绩效系数为空！"});
                }
                //Q2绩效系数
                BigDecimal performanceCoeffQ2 = detailInfo.getPerformanceCoeffQ2();
                if (performanceCoeffQ2 == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的Q2绩效系数为空！"});
                }
                //个人考核系数
                BigDecimal assessmentCoeff = performanceCoeffQ1.add(performanceCoeffQ2).divide(BigDecimal.valueOf(2)).setScale(2, RoundingMode.HALF_UP);
                detailInfo.setAssessmentCoeff(assessmentCoeff);
                //职能系数
                BigDecimal functionCoefficient = detailInfo.getFunctionCoefficient();
                if (functionCoefficient == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的职能系数为空！"});
                }
                //精力投入系数
                BigDecimal energyInputCoeff = detailInfo.getEnergyInputCoeff();
                if (energyInputCoeff == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的精力投入系数为空！"});
                }
                //职级系数
                JobGradeInfo grade = detailInfo.getGrade();
                if (grade == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的职等为空！"});
                }
                BigDecimal rankCoefficient = grade.getBigDecimal("coefficient");
                if (rankCoefficient == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的职级系数为空！"});
                }
                //职能系数 * 精力投入系数 * 出勤率 * 职级系数 * 个人考核系数
                BigDecimal cumulative = functionCoefficient.multiply(energyInputCoeff)
                        .multiply(attendanceRate).multiply(rankCoefficient).multiply(assessmentCoeff).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                detailInfo.setCumulative(cumulative);
                cumulativeSum = cumulativeSum.add(cumulative);
                //个人初始比例
                BigDecimal initialProportion = detailInfo.getInitialProportion();
                if (initialProportion == null) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"员工[" + personName + "]的个人初始比例为空！"});
                }
                if (initialProportion.compareTo(BigDecimal.ZERO) < 0 || initialProportion.compareTo(BigDecimal.ONE) > 0) {
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"个人初始比例只能在[0,1]之间"});
                }
            }
            if (cumulativeSum.compareTo(BigDecimal.ZERO) == 0) {
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{getBusDepMsg(info) + "的(职能系数 * 精力投入系数 * 出勤率 * 职级系数 * 个人考核系数)总和不能为0！"});
            }
            //计算个人奖金
            for (int i = 0; i < assPersonnelDetailCols.size(); i++) {
                BonusCycleBusDepProjectAssPersonnelDetailInfo detailInfo = assPersonnelDetailCols.get(i);
                //职能系数 * 出勤率 * 精力投入系数 * 职级系数 * 个人考核系数
                BigDecimal cumulative = detailInfo.getCumulative();
                //个人奖金占比 = 根据（职能系数 * 出勤率 * 精力投入系数 * 职级系数 * 个人考核系数）/ 同事业部下（职能系数 * 出勤率 * 精力投入系数 * 职级系数 * 个人考核系数）之和计算得出
                BigDecimal bonusProportion = BigDecimal.ZERO;
                if (i == (assPersonnelDetailCols.size() - 1)) {
                    //最后一名做尾差
                    bonusProportion = BigDecimal.ONE.subtract(cumulativeSurplus);
                } else {
                    bonusProportion = cumulative.divide(cumulativeSum, 6, RoundingMode.HALF_UP);
                    cumulativeSurplus = cumulativeSurplus.add(bonusProportion);
                }
                detailInfo.setBonusProportion(bonusProportion);
                //个人初始比例
                BigDecimal initialProportion = detailInfo.getInitialProportion();
                BigDecimal indivBonusAmount = BigDecimal.ZERO;
                if (i == (assPersonnelDetailCols.size() - 1)) {
                    //最后一名做尾差
                    indivBonusAmount = bonusAmount.subtract(bonusAmountSurplus).multiply(initialProportion);
                } else {
                    //本期个人奖金额 = 奖金分包 *  个人奖金占比 * 个人初始比例
                    BigDecimal indivBonusAmountTemp = bonusAmount.multiply(bonusProportion);
                    bonusAmountSurplus = bonusAmountSurplus.add(indivBonusAmountTemp);
                    indivBonusAmount = indivBonusAmountTemp.multiply(initialProportion);
                }
                //本期个人奖金额（万元）
                detailInfo.setIndivBonusAmount(indivBonusAmount);
                //征求意见金额（万元）
                detailInfo.setOpinionAmount(indivBonusAmount);
                //总经理审批金额（实发）（万元）
                detailInfo.setApprovalAmount(indivBonusAmount);
                //更新
                iBonusCycleBusDepProjectAssPersonnelDetail.updatePartial(detailInfo, updateDetailSic);
            }
        } catch (BOSException e) {
            e.printStackTrace();
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
        }
    }

    /**
     * 提交计算
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _submitCalculate(Context ctx,
                                    String billId) throws BOSException, EASBizException {
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        if (BusDepProjectStateEnum.SUBMITED.equals(state)) {
            //状态等于已提交
            info.setState(BusDepProjectStateEnum.SUBMITCALCULATED);
            try {
                //计算
                calculate(ctx, billId);
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, e, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                || BusDepProjectStateEnum.ENABLE.equals(state)
                || BusDepProjectStateEnum.RECHECK.equals(state)) {
            //状态等于禁用 或 初始化 或 已启用 或 已复核
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行提交计算操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 撤回至已提交
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws CmpEASDbException
     */
    @Override
    protected void _withdrawToSubmited(Context ctx, String billId) throws BOSException, EASBizException {
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        if (BusDepProjectStateEnum.SUBMITCALCULATED.equals(state)) {
            //状态等于已提交计算
            info.setState(BusDepProjectStateEnum.SUBMITED);
            try {
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                || BusDepProjectStateEnum.RECHECK.equals(state)
                || BusDepProjectStateEnum.ENABLE.equals(state)) {
            //状态等于禁用 或 初始化 或 已复核 或 启用
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行撤回至已提交操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 提交复核
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _submitRecheck(Context ctx, String billId) throws BOSException, EASBizException {
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        if (BusDepProjectStateEnum.SUBMITCALCULATED.equals(state)) {
            //状态等于已提交计算
            IBonusCycleBusDepProjectAssPersonnelDetail iPersonnelDetail = BonusCycleBusDepProjectAssPersonnelDetailFactory.getLocalInstance(ctx);
            BonusCycleBusDepProjectAssPersonnelDetailCollection assPersonnelDetailCol = iPersonnelDetail.getBonusCycleBusDepProjectAssPersonnelDetailCollection("select person.name,opinionAmount where parent.id = '" + billId + "'");
            for (int i = 0; i < assPersonnelDetailCol.size(); i++) {
                BonusCycleBusDepProjectAssPersonnelDetailInfo assPersonnelDetailInfo = assPersonnelDetailCol.get(i);
                BigDecimal opinionAmount = assPersonnelDetailInfo.getOpinionAmount();
                if (opinionAmount == null) {
                    String personName = assPersonnelDetailInfo.getPerson().getName();
                    throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"分配人员[" + personName + "]的征求意见金额不能为空！"});
                }
            }
            info.setState(BusDepProjectStateEnum.RECHECK);
            try {
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                || BusDepProjectStateEnum.SUBMITED.equals(state)
                || BusDepProjectStateEnum.ENABLE.equals(state)) {
            //状态等于禁用 或 初始化 或 已提交 或 启用
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行提交复核操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 撤回至已计算
     *
     * @param ctx
     * @param billId
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _withdrawToCalculate(Context ctx, String billId) throws BOSException, EASBizException {
        if (StringUtils.isEmpty(billId)) {
            logger.error("单据id不能为空！");
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据id不能为空！"});
        }
        BonusCycleBusDepProjectInfo info = getBonusCycleBusDepProjectInfo(ctx, new ObjectUuidPK(billId), sic);
        CycleStateEnum cycleState = info.getParent().getState();//周期锁定状态
        if (CycleStateEnum.LOCK.equals(cycleState)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"周期已锁定,不允许修改数据！"});
        }
        BusDepProjectStateEnum state = info.getState();
        String alias = state.getAlias();
        if (BusDepProjectStateEnum.RECHECK.equals(state)) {
            //状态等于已复核
            info.setState(BusDepProjectStateEnum.SUBMITCALCULATED);
            try {
                updatePartial(ctx, info, updateSic);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{e.getMessage()});
            }
        } else if (BusDepProjectStateEnum.DISABLE.equals(state)
                || BusDepProjectStateEnum.INITIALIZATION.equals(state)
                || BusDepProjectStateEnum.SUBMITED.equals(state)
                || BusDepProjectStateEnum.ENABLE.equals(state)) {
            //状态等于禁用 或 初始化 或 已提交 或 启用
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(getBusDepMsg(info));
            errorMsg.append(alias).append("，不允许执行撤回至已计算操作！");
            logger.error(errorMsg.toString());
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{errorMsg.toString()});
        }
    }

    /**
     * 同步事业部项目
     *
     * @param ctx
     * @param cycleId 周期id
     * @return
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected String _syncDepProject(Context ctx, String cycleId)
            throws BOSException, EASBizException {
        if (StringUtils.isEmpty(cycleId)) {
            logger.error("周期id不能为空!");
            throw new BOSException("周期id不能为空!");
        }
        String querySql = "SELECT" +
                "    base.fid," +
                "    base.CFProjectType1," +
                "    parent1.fid parentId1," +
                "    parent1.CFProjectType1 parentType1," +
                "    parent2.fid parentId2," +
                "    parent2.CFProjectType1 parentType2" +
                " FROM" +
                "    t_org_admin base" +
                "    left join t_org_admin parent1 on parent1.fid = base.FParentID" +
                "    left join t_org_admin parent2 on parent2.fid = parent1.FParentID" +
                " where" +
                "    base.CFProjectType1 in ('1', '2', '3', '4', '5')" +
                "    and base.fid not in (" +
                "        SELECT" +
                "            case" +
                "                when CFProjectID is null then CFBusDepID" +
                "                else CFProjectID" +
                "            end depId" +
                "        FROM" +
                "            CT_PB_BonusCycleBusDepProject" +
                "        where" +
                "            fparentId = ?" +
                "    )" +
                "    and base.FIsOUSealUp = 0";
        logger.info("syncDepProjectAction_querySql: " + querySql);
        try {
            IRowSet iRowSet = DbUtil.executeQuery(ctx, querySql, new Object[]{cycleId});
            int addCount = 0;
            IBonusCycleBusDepProject iBonusCycleBusDepProject = BonusCycleBusDepProjectFactory.getLocalInstance(ctx);
            while (iRowSet.next()) {
                String fid = iRowSet.getString("fid");//组织id
                String projectType = iRowSet.getString("CFProjectType1");
                String parentId1 = iRowSet.getString("parentId1");//组织父级id
                String parentType1 = iRowSet.getString("parentType1");
                String parentId2 = iRowSet.getString("parentId2");
                String parentType2 = iRowSet.getString("parentType2");
                BonusCycleBusDepProjectInfo info = new BonusCycleBusDepProjectInfo();
                //过滤器
                FilterInfo filterInfo = new FilterInfo();
                FilterItemCollection filterItems = filterInfo.getFilterItems();
                filterItems.add(new FilterItemInfo("parent", cycleId));
                info.put("parent", cycleId);
                if ("1".equals(projectType)) {
                    info.put("busDep", fid);
                    filterItems.add(new FilterItemInfo("busDep", fid));
                    filterItems.add(new FilterItemInfo("project", null));
                } else {
                    if (!StringUtils.isEmpty(parentType1)) {
                        //父级组织类型不为空
                        info.put("busDep", parentId1);
                        filterItems.add(new FilterItemInfo("busDep", parentId1));
                    } else if (!com.kingdee.util.StringUtils.isEmpty(parentType2)) {
                        //祖父级组织类型不为空
                        info.put("busDep", parentId2);
                        info.put("secondcenter", parentId1);
                        filterItems.add(new FilterItemInfo("busDep", parentId2));
                    } else {
                        //事业部组织为根组织
                        info.put("busDep", ROOTID);
                        info.put("secondcenter", parentId1);
                        filterItems.add(new FilterItemInfo("busDep", ROOTID));
                    }
                    info.put("project", fid);
                    filterItems.add(new FilterItemInfo("project", fid));
                }
                info.setType(ProjectType.getEnum(projectType).getAlias());
                info.setState(BusDepProjectStateEnum.INITIALIZATION);
                if (!iBonusCycleBusDepProject.exists(filterInfo)) {
                    try {
                        iBonusCycleBusDepProject.save(info);
                        addCount++;
                    } catch (Exception e) {
                        logger.error("同步事业部项目报错: " + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
            String msg = "新增" + addCount + "条事业部项目数据";
            logger.info(msg);
            return msg;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new BOSException(e.getMessage());
        }
    }

    private String getBusDepMsg(BonusCycleBusDepProjectInfo info) {
        AdminOrgUnitInfo project = info.getProject();
        if (project != null) {
            String projectProject = project.getName();
            return "项目[" + projectProject + "]";
        } else {
            String busdepName = info.getBusDep().getName();
            return "事业部[" + busdepName + "]";
        }
    }


}