package com.awspaas.user.apps.donenow_ctt.event;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.core.delegate.ProcessExecutionContext;
import com.actionsoft.bpms.bpmn.engine.listener.ExecuteListener;
import com.actionsoft.bpms.bpmn.engine.listener.ListenerConst;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.exception.BPMNError;
import com.actionsoft.sdk.local.SDK;
import com.awspaas.user.apps.donenow_ctt.PeriodCalculationUtil;
import com.awspaas.user.apps.donenow_ctt.cttConstant;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

import static com.awspaas.user.apps.donenow_ctt.service.contractService.*;

/**
 * 佣金管理创建保存后事件
 */
public class commissionFormAfterSave extends ExecuteListener {

    public String getDescription() {
        return "佣金管理创建保存后事件，佣金调整后";
    }

    @Override
    public void execute(ProcessExecutionContext processExecutionContext) throws Exception {
        String bindid = processExecutionContext.getProcessInstance().getId();
        String boName = processExecutionContext.getParameterOfString(ListenerConst.FORM_EVENT_PARAM_BONAME);
        UserContext uc = processExecutionContext.getUserContext();

        String _ADJUST = StringUtils.EMPTY;
        if (boName.equals("BO_EU_DNCTT_COMMISSION_ADJUST")) {
            _ADJUST = "_ADJUST";
        }
        //佣金表单和佣金调整表单 保存时触发
        if (boName.equals("BO_EU_DNCTT_COMMISSION") || boName.equals("BO_EU_DNCTT_COMMISSION_ADJUST")) {
            BO commissionBO = processExecutionContext.getBO(boName);
            String COMMISSION_BINDID = bindid;
            if (boName.equals("BO_EU_DNCTT_COMMISSION_ADJUST"))
                COMMISSION_BINDID = commissionBO.getString("COMMISSION_BINDID");
            LocalDate PERIOD_BEGIN_DATE = getLocalDate(commissionBO.get("PERIOD_BEGIN_DATE"));//开始日期
            final LocalDate PERIOD_BEGIN_DATE_final = getLocalDate(commissionBO.get("PERIOD_BEGIN_DATE"));//开始日期  不允许修改
            LocalDate PERIOD_END_DATE = getLocalDate(commissionBO.get("PERIOD_END_DATE"));//结束日期
            String RULE_CATE = commissionBO.getString("RULE_CATE");//佣金规则

            //判断是否重建
            boolean isRebuild = false;
            //结束日期已修改
            String PERIOD_END_DATE_Str = PERIOD_END_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            if (boName.equals("BO_EU_DNCTT_COMMISSION")) {
                //已审批 不允许修改 开始日期和佣金金额
                String PERIOD_BEGIN_DATE_MIN = DBSql.getString("SELECT MIN(PERIOD_BEGIN_DATE) FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE BINDID = '" + bindid + "'");
                String PERIOD_END_DATE_MAX = DBSql.getString("SELECT MAX(PERIOD_END_DATE) FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE BINDID = '" + bindid + "'");
                if (StringUtils.isNotBlank(PERIOD_BEGIN_DATE_MIN) && !PERIOD_BEGIN_DATE.equals(getLocalDate(PERIOD_BEGIN_DATE_MIN))) {
                    //开始日期已修改

                    //已审批不允许修改
                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=?", new Object[]{bindid}) > 0) {
                        throw new BPMNError("已审批不允许修改开始日期和佣金金额");
                    }

                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD_AGENT where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=?", new Object[]{bindid}) > 0) {
                        throw new BPMNError("已审批不允许修改开始日期和佣金金额");
                    }

                    isRebuild = true;
                }

                if (StringUtils.isNotBlank(PERIOD_END_DATE_MAX) && !PERIOD_END_DATE.equals(getLocalDate(PERIOD_END_DATE_MAX))) {

                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=? AND PERIOD_END_DATE>=?", new Object[]{bindid, PERIOD_END_DATE_Str}) > 0) {
                        throw new BPMNError("已审批不允许修改开始日期和佣金金额");
                    }

                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD_AGENT where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=? AND PERIOD_END_DATE>=?", new Object[]{bindid, PERIOD_END_DATE_Str}) > 0) {
                        throw new BPMNError("已审批不允许修改开始日期和佣金金额");
                    }

                    int i = 0;
                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=?", new Object[]{bindid}) == 0) {
                        i = i + 1;
                    }

                    if (DBSql.getInt("select count(1) CNT from BO_EU_DNCTT_COMMISSION_PERIOD_AGENT where APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL AND  BINDID=?", new Object[]{bindid}) == 0) {
                        i = i + 1;
                    }
                    if (i == 2) {
                        isRebuild = true;
                    } else {
                        //修改结束日期

                    }
                }
            } else {
                //校验
                LocalDate EFFECTIVE_DATE = getLocalDate(commissionBO.get("PERIOD_BEGIN_DATE"));//服务生效日期
                String EFFECTIVE_DATE_STR = EFFECTIVE_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

                if (DBSql.getInt("SELECT count(1) FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL and BINDID=? AND  PERIOD_END_DATE>=?", new Object[]{commissionBO.get("COMMISSION_BINDID"), EFFECTIVE_DATE_STR}) > 0) {
                    throw new BPMNError("500", EFFECTIVE_DATE_STR + "之后的佣金周期已被审批，则不能修改到当前日期");
                }

                if (DBSql.getInt("SELECT count(1) FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT WHERE APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL and BINDID=? AND  PERIOD_END_DATE>=?", new Object[]{commissionBO.get("COMMISSION_BINDID"), EFFECTIVE_DATE_STR}) > 0) {
                    throw new BPMNError("500", EFFECTIVE_DATE_STR + "之后的佣金周期已被审批，则不能修改到当前日期");
                }
            }


            //  List<PERIOD> periodList = getPeriodList(RULE_CATE, PERIOD_BEGIN_DATE, PERIOD_END_DATE);//周期


            if (RULE_CATE.equals(cttConstant.COMMISSION_RULE_MONTH)) RULE_CATE = cttConstant.PERIOD_TYPE_ONE_TIME;
            else if (RULE_CATE.equals(cttConstant.COMMISSION_RULE_ONE_TIME))
                RULE_CATE = cttConstant.PERIOD_TYPE_ONE_TIME;
            else if (RULE_CATE.equals(cttConstant.COMMISSION_RULE_QUARTER)) RULE_CATE = cttConstant.PERIOD_TYPE_QUARTER;
            else if (RULE_CATE.equals(cttConstant.COMMISSION_RULE_YEAR)) RULE_CATE = cttConstant.PERIOD_TYPE_YEAR;

            //获取服务周期
            List<PeriodCalculationUtil.Period> periodList = PeriodCalculationUtil.getPeriodList(RULE_CATE, PERIOD_BEGIN_DATE, PERIOD_BEGIN_DATE, PERIOD_END_DATE, true, true, -1,0);

            if (periodList.size() > 0) {
                Connection conn = null;
                try {
                    conn = DBSql.open();
                    conn.setAutoCommit(false);

                    //在未审批的情况下，修改开始日期或结束日期，删除所有佣金周期，重新生成
                    if (isRebuild) {
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE BINDID = ?", new Object[]{bindid});
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT WHERE BINDID = ?", new Object[]{bindid});
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD_SALES WHERE BINDID = ?", new Object[]{bindid});
                    } else {
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE BINDID = ? AND PERIOD_BEGIN_DATE>? ", new Object[]{bindid, PERIOD_END_DATE_Str});
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT WHERE BINDID = ?  AND PERIOD_BEGIN_DATE>? ", new Object[]{bindid, PERIOD_END_DATE_Str});
                        DBSql.update(conn, "DELETE FROM BO_EU_DNCTT_COMMISSION_PERIOD_SALES WHERE BINDID = ?  AND PERIOD_BEGIN_DATE>? ", new Object[]{bindid, PERIOD_END_DATE_Str});
                    }

                    List<BO> commissionAgentList = SDK.getBOAPI().query("BO_EU_DNCTT_COMMISSION_AGENT" + _ADJUST).addQuery("BINDID =", bindid).list();
                    List<BO> commissionSalesList = SDK.getBOAPI().query("BO_EU_DNCTT_COMMISSION_SALES" + _ADJUST).addQuery("BINDID =", bindid).list();

                    if (boName.equals("BO_EU_DNCTT_COMMISSION_ADJUST")) {

                        //当前生效日期之后的调整设置为 作废
                        List<BO> editServiceList = SDK.getBOAPI().query("BO_EU_DNCTT_COMMISSION_ADJUST").connection(conn).addQuery("COMMISSION_BINDID =", COMMISSION_BINDID).addQuery("IS_EFFECTIVE =", "已执行").addQuery("PERIOD_BEGIN_DATE >", PERIOD_BEGIN_DATE_final.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).orderBy("PERIOD_BEGIN_DATE").asc().list();

                        if (editServiceList != null && editServiceList.size() > 0) {
                            //在此次调整之后有新的
                            for (BO editServiceOld : editServiceList) {
                                editServiceOld.set("IS_EFFECTIVE", "作废");
                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_ADJUST", editServiceOld, conn);
                            }
                        }

                        PeriodCalculationUtil.Period firstPeriod = periodList.get(0);
                        if (firstPeriod.getRate().compareTo(BigDecimal.ONE) == 0) {
                            String periodBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE PERIOD_BEGIN_DATE=? AND BINDID=?", new Object[]{firstPeriod.getPeriodBeginDateStr(), bindid});

                            if (StringUtils.isBlank(periodBOID)) {
                                periodBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE PERIOD_BEGIN_DATE<=? AND PERIOD_END_DATE>=? AND BINDID=?", new Object[]{firstPeriod.getPeriodBeginDateStr(), firstPeriod.getPeriodBeginDateStr(), bindid});

                                if (StringUtils.isNotBlank(periodBOID)) {
                                    BO periodBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD", periodBOID);
                                    LocalDate newPERIOD_END_DATE = PERIOD_BEGIN_DATE_final.minusDays(1);

                                    BigDecimal periodRate = divideToBigDecimal(GetPeriodDays(getLocalDate(periodBO.getString("PERIOD_BEGIN_DATE")), newPERIOD_END_DATE), GetPeriodDays(getLocalDate(periodBO.getString("PERIOD_BEGIN_DATE")), getLocalDate(periodBO.getString("PERIOD_END_DATE"))));

                                    String newPERIOD_END_DATE_str = newPERIOD_END_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                                    periodBO.set("PERIOD_END_DATE", newPERIOD_END_DATE_str);
                                    periodBO.set("COMMISSION_DOLLARS", multiply(periodRate, periodBO.get("COMMISSION_DOLLARS")));
                                    periodBO.set("PERIOD_ADJUSTED_PRICE", periodBO.get("COMMISSION_DOLLARS"));
                                    SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD", periodBO, conn);

                                    String LAST_PERIOD_BEGIN_DATE_str = getLocalDate(periodBO.getString("PERIOD_BEGIN_DATE")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

                                    //1 BO_EU_DNCTT_COMMISSION_PERIOD_AGENT
                                    if (commissionAgentList.isEmpty() == false && commissionAgentList.size() > 0) {
                                        for (BO commissionAgentBO : commissionAgentList) {

                                            String periodAgentBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT WHERE PERIOD_BEGIN_DATE=? AND BINDID=? AND AGENT=?", new Object[]{LAST_PERIOD_BEGIN_DATE_str, bindid, commissionAgentBO.get("AGENT")});

                                            if (StringUtils.isBlank(periodAgentBOID)) {
                                                BO periodAgentBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodAgentBOID);
                                                periodAgentBO.set("PERIOD_END_DATE", newPERIOD_END_DATE_str);
                                                periodAgentBO.set("COMMISSION_DOLLARS", multiply(periodRate, periodAgentBO.get("COMMISSION_DOLLARS")));
                                                periodAgentBO.set("PERIOD_ADJUSTED_PRICE", periodAgentBO.get("COMMISSION_DOLLARS"));
                                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodAgentBO, conn);
                                            }
                                        }
                                    }

                                    //2 BO_EU_DNCTT_COMMISSION_PERIOD_SALES
                                    if (commissionSalesList.isEmpty() == false && commissionSalesList.size() > 0) {
                                        for (BO commissionSalesBO : commissionSalesList) {

                                            String periodSalesBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD_SALES WHERE PERIOD_BEGIN_DATE=? AND BINDID=? AND SALESPERSON=?", new Object[]{LAST_PERIOD_BEGIN_DATE_str, bindid, commissionSalesBO.get("SALESPERSON")});

                                            if (StringUtils.isNotBlank(periodSalesBOID)) {
                                                BO periodSalesBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodSalesBOID);
                                                periodSalesBO.set("PERIOD_END_DATE", newPERIOD_END_DATE_str);
                                                periodSalesBO.set("COMMISSION_DOLLARS", multiply(periodRate, periodSalesBO.get("COMMISSION_DOLLARS")));
                                                periodSalesBO.set("PERIOD_ADJUSTED_PRICE", periodSalesBO.get("COMMISSION_DOLLARS"));
                                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodSalesBO, conn);
                                            }
                                        }
                                    }

                                }
                            }
                        }
                    }


                    for (PeriodCalculationUtil.Period period : periodList) {

                        String periodBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD WHERE PERIOD_BEGIN_DATE=? AND BINDID=?", new Object[]{period.getPeriodBeginDateStr(), COMMISSION_BINDID});
                        if (StringUtils.isNotBlank(periodBOID)) {
                            BO periodBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD", periodBOID);
                            if (StringUtils.isNotBlank(periodBO.getString("APPROVE_AND_POST_USER_ID")) && StringUtils.isNotBlank(periodBO.getString("APPROVE_AND_POST_DATE"))) {
                                //已审批，不能修改
                            } else {
                                periodBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                                periodBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionBO.get("COMMISSION_DOLLARS")));
                                periodBO.set("PERIOD_ADJUSTED_PRICE", periodBO.get("COMMISSION_DOLLARS"));
                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD", periodBO, conn);
                            }
                            period.setCommissionPeriodId(periodBO.getId());
                        } else {
                            //佣金周期
                            BO periodBO = new BO();
                            periodBO.set("ZB_FEE_DATE", period.getPeriodMonthStr());
                            periodBO.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
                            periodBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                            periodBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionBO.get("COMMISSION_DOLLARS")));
                            periodBO.set("PERIOD_ADJUSTED_PRICE", periodBO.get("COMMISSION_DOLLARS"));
                            periodBO.setBindId(COMMISSION_BINDID);
                            SDK.getBOAPI().createDataBO("BO_EU_DNCTT_COMMISSION_PERIOD", periodBO, uc, conn);
                            period.setCommissionPeriodId(periodBO.getId());
                        }
                        //二级代理提成
                        if (commissionAgentList.isEmpty() == false && commissionAgentList.size() > 0) {
                            for (BO commissionAgentBO : commissionAgentList) {

                                String periodAgentBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT WHERE PERIOD_BEGIN_DATE=? AND BINDID=? AND AGENT=?", new Object[]{period.getPeriodBeginDateStr(), COMMISSION_BINDID, commissionAgentBO.get("AGENT")});

                                if (StringUtils.isNotBlank(periodAgentBOID)) {
                                    BO periodAgentBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodAgentBOID);
                                    if (StringUtils.isNotBlank(periodAgentBO.getString("APPROVE_AND_POST_USER_ID")) && StringUtils.isNotBlank(periodAgentBO.getString("APPROVE_AND_POST_DATE"))) {
                                        //已审批，不能修改
                                    } else {
                                        periodAgentBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                                        periodAgentBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionAgentBO.get("COMMISSION_DOLLARS")));
                                        periodAgentBO.set("PERIOD_ADJUSTED_PRICE", periodAgentBO.get("COMMISSION_DOLLARS"));
                                        SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodAgentBO, conn);
                                    }
                                } else {
                                    BO periodAgentBO = new BO();
                                    periodAgentBO.set("AGENT", commissionAgentBO.get("AGENT"));
                                    periodAgentBO.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
                                    periodAgentBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                                    periodAgentBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionAgentBO.get("COMMISSION_DOLLARS")));
                                    periodAgentBO.set("PERIOD_ADJUSTED_PRICE", periodAgentBO.get("COMMISSION_DOLLARS"));
                                    periodAgentBO.set("COMMISSION_PERIOD_ID", period.getCommissionPeriodId());
                                    periodAgentBO.setBindId(COMMISSION_BINDID);
                                    SDK.getBOAPI().createDataBO("BO_EU_DNCTT_COMMISSION_PERIOD_AGENT", periodAgentBO, uc, conn);

                                }
                            }
                        }

                        //销售员佣金周期
                        if (commissionSalesList.isEmpty() == false && commissionSalesList.size() > 0) {
                            for (BO commissionSalesBO : commissionSalesList) {

                                String periodSalesBOID = DBSql.getString(conn, "SELECT ID FROM BO_EU_DNCTT_COMMISSION_PERIOD_SALES WHERE PERIOD_BEGIN_DATE=? AND BINDID=? AND SALESPERSON=?", new Object[]{period.getPeriodBeginDateStr(), COMMISSION_BINDID, commissionSalesBO.get("SALESPERSON")});

                                if (StringUtils.isNotBlank(periodSalesBOID)) {
                                    BO periodSalesBO = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD_SALES", periodSalesBOID);
                                    if (StringUtils.isNotBlank(periodSalesBO.getString("APPROVE_AND_POST_USER_ID")) && StringUtils.isNotBlank(periodSalesBO.getString("APPROVE_AND_POST_DATE"))) {
                                        //已审批，不能修改
                                    } else {
                                        periodSalesBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                                        periodSalesBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionSalesBO.get("COMMISSION_DOLLARS")));
                                        periodSalesBO.set("PERIOD_ADJUSTED_PRICE", periodSalesBO.get("COMMISSION_DOLLARS"));
                                        SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD_SALES", periodSalesBO, conn);
                                    }
                                } else {
                                    BO periodSalesBO = new BO();
                                    periodSalesBO.set("SALESPERSON", commissionSalesBO.get("SALESPERSON"));
                                    periodSalesBO.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
                                    periodSalesBO.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
                                    periodSalesBO.set("COMMISSION_DOLLARS", multiply(period.getRate(), commissionSalesBO.get("COMMISSION_DOLLARS")));
                                    periodSalesBO.set("PERIOD_ADJUSTED_PRICE", periodSalesBO.get("COMMISSION_DOLLARS"));
                                    periodSalesBO.set("COMMISSION_PERIOD_ID", period.getCommissionPeriodId());
                                    periodSalesBO.setBindId(COMMISSION_BINDID);
                                    SDK.getBOAPI().createDataBO("BO_EU_DNCTT_COMMISSION_PERIOD_SALES", periodSalesBO, uc, conn);
                                }
                            }
                        }
                    }


                    //更新佣金
                    if (boName.equals("BO_EU_DNCTT_COMMISSION_ADJUST")) {
                        commissionBO.set("IS_EFFECTIVE", "已执行");
                        SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_ADJUST", commissionBO, conn);

                        BO orgCommissionBO = SDK.getBOAPI().getByProcess("BO_EU_DNCTT_COMMISSION", COMMISSION_BINDID);

                        orgCommissionBO.set("DOLLARS", commissionBO.get("DOLLARS"));
                        orgCommissionBO.set("COMMISSION_DOLLARS", commissionBO.get("COMMISSION_DOLLARS"));

                        SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION", orgCommissionBO, conn);


                        //二级代理提成
                        if (commissionAgentList.isEmpty() == false && commissionAgentList.size() > 0) {
                            for (BO commissionAgentBO : commissionAgentList) {

                                BO orgCommissionAgentBO = SDK.getBOAPI().query("BO_EU_DNCTT_COMMISSION_AGENT").addQuery("BINDID =", COMMISSION_BINDID).addQuery("AGENT =", commissionAgentBO.get("AGENT")).detail();

                                orgCommissionAgentBO.set("RATIO", commissionAgentBO.get("RATIO"));
                                orgCommissionAgentBO.set("DOLLARS", commissionAgentBO.get("DOLLARS"));
                                orgCommissionAgentBO.set("TAX_DEDUCT", commissionAgentBO.get("TAX_DEDUCT"));
                                orgCommissionAgentBO.set("COMMISSION_DOLLARS", commissionAgentBO.get("COMMISSION_DOLLARS"));
                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_AGENT", orgCommissionAgentBO, conn);
                            }

                        }

                        //销售员佣金周期
                        if (commissionSalesList.isEmpty() == false && commissionSalesList.size() > 0) {
                            for (BO commissionSalesBO : commissionSalesList) {
                                BO orgCommissionSalesBO = SDK.getBOAPI().query("BO_EU_DNCTT_COMMISSION_SALES").addQuery("BINDID =", COMMISSION_BINDID).addQuery("SALESPERSON =", commissionSalesBO.get("SALESPERSON")).detail();
                                orgCommissionSalesBO.set("RATIO", commissionSalesBO.get("RATIO"));
                                orgCommissionSalesBO.set("DOLLARS", commissionSalesBO.get("DOLLARS"));
                                orgCommissionSalesBO.set("TAX_DEDUCT", commissionSalesBO.get("TAX_DEDUCT"));
                                orgCommissionSalesBO.set("COMMISSION_DOLLARS", commissionSalesBO.get("COMMISSION_DOLLARS"));
                                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_SALES", orgCommissionSalesBO, conn);

                            }

                        }
                    }

                    conn.commit();
                } catch (SQLException e) {
                    e.printStackTrace();
                    conn.rollback();
                } finally {
                    if (conn != null) DBSql.close(conn);
                }

            }

        }


    }

    /**
     * 计算当前季度的总天数
     */
    private static int getDaysInCurrentQuarter(LocalDate date) {
        // 获取当前月份
        Month currentMonth = date.getMonth();
        // 确定当前季度的起始月份和结束月份
        Month startMonth = getQuarterStartMonth(currentMonth);
        Month endMonth = getQuarterEndMonth(currentMonth);

        // 构建季度的第一天（当月第一天）
        LocalDate quarterStart = LocalDate.of(date.getYear(), startMonth, 1);

        // 构建季度的最后一天（当月最后一天）
        LocalDate quarterEnd = LocalDate.of(date.getYear(), endMonth, endMonth.length(date.isLeapYear()) // 考虑闰年2月的天数
        );

        // 计算两个日期之间的天数（包含首尾两天）
        return (int) ChronoUnit.DAYS.between(quarterStart, quarterEnd) + 1;
    }

    /**
     * 获取当前季度的起始月份
     */
    private static Month getQuarterStartMonth(Month month) {
        int monthValue = month.getValue();
        if (monthValue <= 3) {
            return Month.JANUARY; // 第一季度：1-3月
        } else if (monthValue <= 6) {
            return Month.APRIL;   // 第二季度：4-6月
        } else if (monthValue <= 9) {
            return Month.JULY;    // 第三季度：7-9月
        } else {
            return Month.OCTOBER; // 第四季度：10-12月
        }
    }

    /**
     * 获取当前季度的结束月份
     */
    private static Month getQuarterEndMonth(Month month) {
        int monthValue = month.getValue();
        if (monthValue <= 3) {
            return Month.MARCH;   // 第一季度结束月
        } else if (monthValue <= 6) {
            return Month.JUNE;    // 第二季度结束月
        } else if (monthValue <= 9) {
            return Month.SEPTEMBER; // 第三季度结束月
        } else {
            return Month.DECEMBER;  // 第四季度结束月
        }
    }

    public static LocalDate getCommissNextPeriodStart(LocalDate start, String periodType) {
        // 根据不同的周期类型计算下一周期的开始时间
        switch (periodType) {
            case cttConstant.COMMISSION_RULE_MONTH:
                // 如果是月周期，则在当前时间基础上增加1个月
                return start.plus(1, ChronoUnit.MONTHS);
            case cttConstant.COMMISSION_RULE_QUARTER:
                // 如果是季度周期，则在当前时间基础上增加3个月
                return start.plus(3, ChronoUnit.MONTHS);
            case cttConstant.COMMISSION_RULE_YEAR:
                // 如果是年周期，则在当前时间基础上增加1年
                return start.plus(1, ChronoUnit.YEARS);
            default:
                // 如果周期类型不匹配任何已知类型，则返回原始开始时间
                return start;
        }
    }

    /**
     * 获取周期列表
     * @param RULE_CATE
     * @param PERIOD_BEGIN_DATE
     * @param PERIOD_END_DATE
     * @return
     */
    private List<PERIOD> getPeriodList(String RULE_CATE, LocalDate PERIOD_BEGIN_DATE, LocalDate PERIOD_END_DATE) {
        List<PERIOD> periodList = new ArrayList<>();
        //一次性收费
        if (RULE_CATE.equals(cttConstant.COMMISSION_RULE_ONE_TIME)) {
            PERIOD period = new PERIOD();
            period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
            period.setPeriodEndDate(PERIOD_END_DATE);
            period.setRate(BigDecimal.ONE);
            periodList.add(period);
        } else {
            LocalDate START_DATE = null;
            LocalDate currLastDay = null;
            int periodDays = 0;
            switch (RULE_CATE) {
                case cttConstant.COMMISSION_RULE_MONTH://按月支付
                {
                    if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1) {
                        currLastDay = PERIOD_BEGIN_DATE.with(TemporalAdjusters.lastDayOfMonth());
                        periodDays = PERIOD_BEGIN_DATE.lengthOfMonth();
                    }
                }
                break;
                case cttConstant.COMMISSION_RULE_QUARTER://按季支付
                {
                    //如果不是季度第一天
                    if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1 || (PERIOD_BEGIN_DATE.getMonthValue() - 1) % 3 != 0) {
                        Month endMonth = getQuarterEndMonth(PERIOD_BEGIN_DATE.getMonth());
                        currLastDay = LocalDate.of(PERIOD_BEGIN_DATE.getYear(), endMonth, endMonth.length(PERIOD_BEGIN_DATE.isLeapYear()) // 考虑闰年2月的天数
                        );
                        periodDays = getDaysInCurrentQuarter(PERIOD_BEGIN_DATE);
                    }
                }
                break;
                case cttConstant.COMMISSION_RULE_YEAR://按年支付
                {
                    //如果不是年第一天
                    if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1 || PERIOD_BEGIN_DATE.getMonthValue() != 1) {
                        //所在年最后一天
                        currLastDay = LocalDate.of(PERIOD_BEGIN_DATE.getYear(), 12, 31);
                        periodDays = PERIOD_BEGIN_DATE.lengthOfYear();
                    }
                }
                break;
                default: {
                    //报错，类型异常
                    return null;
                }
            }

            if (currLastDay != null) {
                if (currLastDay.isBefore(PERIOD_END_DATE)) {
                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
                    period.setPeriodEndDate(currLastDay);

                    BigDecimal periodRate = divideToBigDecimal(GetPeriodDays(PERIOD_BEGIN_DATE, currLastDay), periodDays);
                    period.setRate(periodRate);

                    periodList.add(period);

                    START_DATE = currLastDay.plusDays(1);//周期开始日期
                } else {
                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
                    period.setPeriodEndDate(PERIOD_END_DATE);

                    BigDecimal periodRate = divideToBigDecimal(GetPeriodDays(PERIOD_BEGIN_DATE, PERIOD_END_DATE), periodDays);
                    period.setRate(periodRate);

                    periodList.add(period);
                }
            } else {
                START_DATE = PERIOD_BEGIN_DATE;
            }
            //循环
            if (START_DATE != null && START_DATE.isBefore(PERIOD_END_DATE)) {

                while (!START_DATE.isAfter(PERIOD_END_DATE)) {
                    LocalDate periodEnd = getCommissNextPeriodStart(START_DATE, RULE_CATE).minusDays(1);//本周期结束时间

                    BigDecimal periodRate = BigDecimal.ONE;

                    if (periodEnd.isAfter(PERIOD_END_DATE)) {//如果结束日期大于合同结束日期，则计算结束日期和合同结束日期的差值，并计算该差值占整周期的比例
                        periodRate = divideToBigDecimal(GetPeriodDays(START_DATE, PERIOD_END_DATE), GetPeriodDays(START_DATE, periodEnd));
                        periodEnd = PERIOD_END_DATE;
                    }

                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(START_DATE);
                    period.setPeriodEndDate(periodEnd);
                    period.setRate(periodRate);
                    periodList.add(period);

                    if (periodEnd != null) {
                        START_DATE = periodEnd.plusDays(1);
                    }
                }
            }

        }
        return periodList;
    }


    /**
     * 周期
     */
    private class PERIOD {
        private LocalDate PERIOD_BEGIN_DATE;
        private LocalDate PERIOD_END_DATE;

        private BigDecimal RATE;

        private String COMMISSION_PERIOD_ID;

        public void setPeriodBeginDate(LocalDate periodBeginDate) {
            this.PERIOD_BEGIN_DATE = periodBeginDate;
        }

        public void setPeriodEndDate(LocalDate periodEndDate) {
            this.PERIOD_END_DATE = periodEndDate;
        }

        public void setRate(BigDecimal rate) {
            this.RATE = rate;
        }

        public void setCommissionPeriodId(String commissionPeriodId) {
            this.COMMISSION_PERIOD_ID = commissionPeriodId;
        }

        public LocalDate getPeriodBeginDate() {
            return PERIOD_BEGIN_DATE;
        }

        public LocalDate getPeriodEndDate() {
            return PERIOD_END_DATE;
        }

        public String getPeriodBeginDateStr() {
            return PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        public String getPeriodMonthStr() {
            return PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyyMM"));
        }

        public String getPeriodEndDateStr() {
            return PERIOD_END_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        public BigDecimal getRate() {
            return RATE;
        }

        public String getCommissionPeriodId() {
            return COMMISSION_PERIOD_ID;
        }
    }
}
