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

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.commons.database.RowMap;
import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.server.bind.annotation.Controller;
import com.actionsoft.bpms.server.bind.annotation.Mapping;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.sdk.local.SDK;
import com.actionsoft.sdk.local.api.Logger;
import com.awspaas.user.apps.donenow_ctt.cttConstant;
import com.awspaas.user.apps.donenow_ctt.service.contractService;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.awspaas.user.apps.donenow_ctt.service.contractService.GetEntryCost;
import static com.awspaas.user.apps.donenow_ctt.service.contractService.getLocalDate;

@Controller
public class contractApproveController {
    private static final Logger contractLogger = SDK.getLogAPI().getLogger(contractApproveController.class);//记录日志

    /**
     * 定期服务审批
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.approve_service")
    public ResponseObject approveService(UserContext uc, String approveDate, String approveIds) throws SQLException {
        if (StringUtils.isBlank(approveDate) || StringUtils.isBlank(approveIds))
            return ResponseObject.newErrResponse("参数错误");

        contractService.getInstance().postRecurringServices(uc, approveDate, approveIds);

        return ResponseObject.newOkResponse();
    }

    /**
     * 里程碑审批
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_milestone")
    public ResponseObject approveMilestone(UserContext uc, String approveDate, String approveIds) throws SQLException {
        if (StringUtils.isBlank(approveDate) || StringUtils.isBlank(approveIds))
            return ResponseObject.newErrResponse("参数错误");

        contractService.getInstance().postMilestone(uc, approveDate, approveIds);
        return ResponseObject.newOkResponse();
    }

    /**
     * / 调整订阅周期、定期服务（服务、服务调整、服务包、服务包调整、初始费用）、成本的计费总价
     * @param uc
     * @param periodPrice
     * @param id
     * @param type
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_updateExtendedPrice")
    public ResponseObject updateExtendedPrice(UserContext uc, Double periodPrice, String id, int type) throws SQLException {
        if (type == cttConstant.APPROVE_SUBSCRIPTIONS)//订阅
        {

        } else if (type == cttConstant.APPROVE_RECURRING_SERVICES)//定期服务审批
        {

            BO ccBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT", id);//合同
            if (ccBO != null) {
                ccBO.set("ADJUST_SETUP_FEE", periodPrice);//调整后合同初始费用
                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", ccBO);
            } else {
                BO ccsaBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST", id);//定期服务调整
                if (ccsaBO != null) {
                    ccsaBO.set("ADJUST_PRORATED_PRICE_CHANGE", periodPrice);//调整后合同初始费用
                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST", ccsaBO);
                } else {
                    BO ccspBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", id);//周期服务
                    if (ccspBO != null) {
                        ccspBO.set("PERIOD_ADJUSTED_PRICE", periodPrice);//调整后合同初始费用
                        SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", ccspBO);
                    }
                }
            }
        }

        return ResponseObject.newOkResponse();
    }

    /**
     * 审批初始费用
     * @param uc
     * @param ids
     * @param type
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_restoreInitialPrice")
    public ResponseObject restoreInitialPrice(UserContext uc, String ids, int type) throws SQLException {
        if (type == cttConstant.APPROVE_SUBSCRIPTIONS)//订阅
        {

        } else if (type == cttConstant.APPROVE_RECURRING_SERVICES)//定期服务审批
        {
            for (String id : ids.split(",")) {

                BO ccBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT", id);//合同
                if (ccBO != null) {
                    ccBO.set("ADJUST_SETUP_FEE", ccBO.get("SETUP_FEE"));//调整后合同初始费用
                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", ccBO);
                } else {
                    BO ccsaBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST", id);//定期服务调整
                    if (ccsaBO != null) {
                        ccsaBO.set("ADJUST_PRORATED_PRICE_CHANGE", ccsaBO.get("PRORATED_PRICE_CHANGE"));//调整后合同初始费用
                        SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST", ccsaBO);
                    } else {
                        BO ccspBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", id);//周期服务
                        if (ccspBO != null) {
                            ccspBO.set("PERIOD_ADJUSTED_PRICE", ccspBO.get("PERIOD_PRICE"));//调整后合同初始费用
                            SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", ccspBO);
                        }
                    }
                }
            }
        }
        return ResponseObject.newOkResponse();
    }

    /**
     * 审批合同产品
     * @param uc
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_cost")
    public ResponseObject cost(UserContext uc, String approveDate, String approveIds) throws SQLException {

        boolean result = contractService.getInstance().postCost(uc, approveDate, approveIds);

        return result ? ResponseObject.newOkResponse() : ResponseObject.newErrResponse("审批失败");
    }

    /**
     * 撤销定期服务
     * @param uc
     * @param ids
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_recurring_services")
    public ResponseObject revokeRecurringServices(UserContext uc, String ids) throws SQLException {
        String result = contractService.getInstance().revokeRecurringServices(uc, ids);
        if (StringUtils.isNotBlank(result)) return ResponseObject.newErrResponse(result);

        contractLogger.info("撤销定期服务成功");
        return ResponseObject.newOkResponse();
    }

    /**
     * 撤销里程碑审批
     * @param uc
     * @param ids
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_milestones")
    public ResponseObject revokeMilestones(UserContext uc, String ids) throws SQLException {
        String result = contractService.getInstance().revokeMilestones(uc, ids);
        if (StringUtils.isNotBlank(result)) return ResponseObject.newErrResponse(result);

        contractLogger.info("撤销里程碑成功");
        return ResponseObject.newOkResponse();
    }

    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_cost")
    public ResponseObject revokeCost(UserContext uc, String ids) throws SQLException {
        String result = contractService.getInstance().revokeCost(uc, ids);
        if (StringUtils.isNotBlank(result)) return ResponseObject.newErrResponse(result);

        contractLogger.info("撤销合同成本成功");
        return ResponseObject.newOkResponse();
    }

    /**
     * 修改税
     * @param uc
     * @param id
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.modify_taxRate")
    public ResponseObject modifyTaxRate(UserContext uc, String id) throws SQLException {

        BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);

        String account_id = bo.getString("ACCOUNT_ID");
        String extended_price = bo.getString("EXTENDED_PRICE");
        String tax_category_id = bo.getString("TAX_CATEGORY_ID");
        String effective_tax_rate = bo.getString("EFFECTIVE_TAX_RATE");
        String tax_dollars = bo.getString("TAX_DOLLARS");

        List<RowMap> effectiveTaxRateList = DBSql.getMaps("select tax_cate_id as taxCateId,total_effective_tax_rate as effectiveTaxRate from bo_eu_dnd_tax_region_cate where tax_region_id IN (select tax_region_id from bo_eu_dncrm_account where id=?)", new Object[]{account_id});

        List<RowMap> taxCateList = DBSql.getMaps("SELECT oid,NAME FROM bo_eu_dnd_general WHERE general_table_id=44 AND CLOSED=0 AND ORGID=? AND oid in(select tax_cate_id from bo_eu_dnd_tax_region_cate where tax_region_id in (select tax_region_id from bo_eu_dncrm_account where id=?))", new Object[]{uc.getCompanyModel().getId(), account_id});

        Map<String, Object> map = new HashMap<>();
        map.put("taxCateList", taxCateList);
        map.put("effectiveTaxRateList", effectiveTaxRateList);

        map.put("taxCateId", tax_category_id);
        map.put("effectiveTaxRate", effective_tax_rate);
        map.put("taxDollars", tax_dollars);
        map.put("extendedPrice", extended_price);

        ResponseObject responseObject = ResponseObject.newOkResponse();
        responseObject.setData(map);

        return responseObject;
    }

    /**
     * 修改税保存
     * @param uc
     * @param id
     * @param taxCateId
     * @param effectiveTaxRate
     * @param taxDollars
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.modify_taxRate_save")
    public ResponseObject modifyTaxRateSave(UserContext uc, String id, String taxCateId, String effectiveTaxRate, String taxDollars) throws SQLException {
        BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
        bo.set("TAX_CATEGORY_ID", taxCateId);
        bo.set("tax_category_name", DBSql.getString("SELECT NAME FROM bo_eu_dnd_general WHERE general_table_id=44 AND oid=?", new Object[]{taxCateId}));
        bo.set("EFFECTIVE_TAX_RATE", effectiveTaxRate);
        bo.set("TAX_DOLLARS", taxDollars);
        SDK.getBOAPI().update("BO_EU_DNCRM_ACCOUNT_DEDUCTION", bo);
        return ResponseObject.newOkResponse();
    }

    /**
     * 批量审批人工
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_labor")
    public ResponseObject laborApprove(UserContext uc, String approveDate, String approveIds) {
        String[] IdArr = approveIds.split(",");
        String sql = "SELECT * FROM VIEW_EU_DNV_PENDING_LABOR WHERE ID IN(";
        for (int i = 0; IdArr.length > i; i++) {
            sql += "?,";
        }
        sql = sql.substring(0, sql.length() - 1) + ")";
        List<RowMap> list = DBSql.getMaps(sql, Arrays.stream(IdArr).toArray());
        String ORGID = uc.getCompanyModel().getId();
        LocalDate thisDate = getLocalDate(approveDate);//审批时间
        for (RowMap thisWorkEntry : list) {

            for (String key : thisWorkEntry.keySet()) {
                thisWorkEntry.put(key.toUpperCase(), thisWorkEntry.get(key) == null ? "" : thisWorkEntry.get(key));
            }

            BO oldEntry = SDK.getBOAPI().get("BO_EU_DNSDK_WORK_ENTRY", thisWorkEntry.getString("ID"));
            String COST_CODE_ID = oldEntry.getString("COST_CODE_ID");//获取成本代码ID

            System.out.println("COST_CODE_ID:" + COST_CODE_ID);

            RowMap thisTaxCate = null;//税收种类
            if (StringUtils.isNotBlank(COST_CODE_ID)) {
                RowMap costCode = DBSql.getMap("SELECT * FROM BO_EU_DND_COST_CODE WHERE OID=? AND ORGID=?", new Object[]{COST_CODE_ID, ORGID});
                if (costCode != null && StringUtils.isNotBlank(costCode.getString("TAX_CATEGORY_ID"))) {
                    thisTaxCate = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=?  AND ORGID=?", new Object[]{costCode.getString("TAX_CATEGORY_ID"), ORGID});
                }
            }

            System.out.println("TAX_CATEGORY_ID:" + thisTaxCate.getString("OID"));

            Double tax_rate = 0.0;
            RowMap thisTaxRegion = null;
            RowMap thisAccount = DBSql.getMap("SELECT * FROM BO_EU_DNCRM_ACCOUNT WHERE ID=?", new Object[]{thisWorkEntry.getString("ACCOUNT_ID")});
            // 获取税收信息
            if (thisAccount != null && StringUtils.isNotBlank(thisAccount.getString("TAX_REGION_ID"))) {
                thisTaxRegion = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=? AND ORGID=?", new Object[]{thisAccount.getString("TAX_REGION_ID"), ORGID});
            }

            System.out.println("TAX_REGION_ID:" + thisTaxRegion.getString("OID"));

            if (thisTaxCate != null && thisTaxRegion != null) {

                RowMap thisTax = DBSql.getMap("SELECT * FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID=? AND TAX_CATEGORY_ID=? AND ORGID=?", new Object[]{thisTaxRegion.getString("OID"), thisTaxCate.getString("OID"), ORGID});
                if (thisTax != null) {
                    tax_rate = thisTax.getDouble("TOTAL_EFFECTIVE_TAX_RATE");
                }
            }


            Double block_hour_multiplier = 0.0;

            RowMap thisConRole = DBSql.getMap("SELECT * FROM BO_EU_DNCTT_CONTRACT_RATE WHERE CONTRACT_ID=? AND ROLE_ID=?", new Object[]{thisWorkEntry.getString("CONTRACT_ID"), thisWorkEntry.getString("ROLE_ID")});

            if (thisConRole != null) {
                block_hour_multiplier = thisConRole.getDouble("BLOCK_HOUR_MULTIPLIER");//乘数
            } else {
                RowMap thisRole = DBSql.getMap("SELECT * FROM BO_EU_DNSYS_ROLE WHERE ID=?", new Object[]{thisWorkEntry.getString("ROLE_ID")});
                if (thisRole != null) {
                    block_hour_multiplier = thisRole.getDouble("HOURLY_FACTOR");//角色时间系数
                }
            }


            BO thisDed = new BO();
            thisDed.set("TYPE_ID", "1318");
            thisDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
            thisDed.set("POSTED_DATE", thisDate);
            thisDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
            thisDed.set("EXTENDED_PRICE", thisWorkEntry.getDouble("DOLLARS"));

            thisDed.set("ACCOUNT_ID", thisWorkEntry.getString("ACCOUNT_ID"));
            thisDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
            thisDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
            thisDed.set("BILL_ACCOUNT_ID", thisWorkEntry.getString("BILL_ACCOUNT_ID"));

            thisDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
            thisDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));

            thisDed.set("EFFECTIVE_TAX_RATE", tax_rate);

            thisDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
            thisDed.set("QUANTITY", thisWorkEntry.get("QUANTITY"));
            thisDed.set("RATE", thisWorkEntry.get("RATE"));
            thisDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
            thisDed.set("EXTENDED_COST", thisWorkEntry.get("COST"));
            if (thisTaxCate != null)
                thisDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("OID"));

            //是否免税
            if ((thisAccount == null || !thisAccount.getString("IS_TAX_EXEMPT").equals("1")) && tax_rate > 0) {
                thisDed.set("TAX_DOLLARS", thisWorkEntry.getDouble("DOLLARS") * (1 - 1 / (1 + tax_rate)));
            }
            if (StringUtils.isBlank(thisDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisDed.getString("ACCOUNT_ID")))
                thisDed.set("BILL_ACCOUNT_ID", thisDed.get("ACCOUNT_ID"));

            dn.recordFormChanges.record(uc, thisDed, "审批提交工时");
            SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisDed, uc);

            oldEntry.set("APPROVE_AND_POST_DATE", thisDate);
            oldEntry.set("APPROVE_AND_POST_USER_ID", uc.getUID());
            dn.recordFormChanges.record(uc, oldEntry, "审批提交工时");
            SDK.getBOAPI().update("BO_EU_DNSDK_WORK_ENTRY", oldEntry);
        }
        return ResponseObject.newOkResponse();
    }

    /**
     * 工时审批
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_labor2")
    public ResponseObject laborApprove2(UserContext uc, String approveDate, String approveIds) {
        String[] IdArr = approveIds.split(",");
        String sql = "SELECT * FROM VIEW_EU_DNV_PENDING_LABOR WHERE ID IN(";
        for (int i = 0; IdArr.length > i; i++) {
            sql += "?,";
        }
        sql = sql.substring(0, sql.length() - 1) + ")";
        List<RowMap> list = DBSql.getMaps(sql, Arrays.stream(IdArr).toArray());
        String ORGID = uc.getCompanyModel().getId();
        for (RowMap rowMap : list) {
            String COST_CODE_ID = getString(rowMap, "COST_CODE_ID");//获取成本代码ID
            RowMap thisTaxCate = null;//税收种类
            if (StringUtils.isNotBlank(COST_CODE_ID)) {
                RowMap costCode = DBSql.getMap("SELECT * FROM BO_EU_DND_COST_CODE WHERE OID=? AND ORGID=?", new Object[]{COST_CODE_ID, ORGID});
                if (costCode != null && StringUtils.isNotBlank(costCode.getString("TAX_CATEGORY_ID"))) {
                    thisTaxCate = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=?  AND ORGID=?", new Object[]{costCode.getString("TAX_CATEGORY_ID"), ORGID});
                }
            }

            RowMap thisContract = null;//合同
            RowMap thisAccount = null;
            String CONTRRACT_ID = getString(rowMap, "CONTRACT_ID");

            if (StringUtils.isNotBlank(CONTRRACT_ID)) {
                thisContract = DBSql.getMap("SELECT * FROM BO_EU_DNCTT_CONTRACT WHERE ID=?", new Object[]{CONTRRACT_ID});

                RowMap thatAccount = DBSql.getMap("SELECT * FROM BO_EU_DNCRM_ACCOUNT WHERE ID IN (SELECT ACCOUNT_ID FROM BO_EU_DNCTT_CONTRACT WHERE ID=?)", new Object[]{CONTRRACT_ID});
                if (thatAccount != null)
                    thisAccount = thatAccount;
            }


            RowMap thisTaxRegion = null;
            Double tax_rate = 0.0;//税率
            String TASK_ID = rowMap.getString("TASK_ID");
            if (StringUtils.isNotBlank(TASK_ID)) {
                RowMap thatAccount = DBSql.getMap("SELECT * FROM BO_EU_DNCRM_ACCOUNT WHERE ID IN (SELECT ACCOUNT_ID FROM BO_EU_DNSDK_TASK WHERE ID=?)", new Object[]{TASK_ID});
                if (thatAccount != null)
                    thisAccount = thatAccount;
            }

            String thisContractId = thisContract == null ? "null" : thisContract.getString("ID");
            String ROLE_ID = rowMap.getString("ROLE_ID");

            Double laborRate = 0.0;
            //该员工的费率
            try {
                laborRate = DBSql.getDouble("SELECT f_get_labor_rate(" + thisContractId + "," + COST_CODE_ID + "," + ROLE_ID + "," + ORGID + ") as laborRate", "laborRate");
            } catch (Exception e) {
                System.out.println("获取费率异常" + e.getMessage());
            }


            // 获取税收信息
            if (thisAccount != null && StringUtils.isNotBlank(thisAccount.getString("TAX_REGION_ID"))) {
                thisTaxRegion = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=? AND ORGID=?", new Object[]{thisAccount.getString("TAX_REGION_ID"), ORGID});
            }
            if (thisTaxCate != null && thisTaxRegion != null) {

                RowMap thisTax = DBSql.getMap("SELECT * FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID=? AND TAX_CATEGORY_ID=? AND ORGID=?", new Object[]{thisTaxRegion.getString("OID"), thisTaxCate.getString("OID"), ORGID});
                if (thisTax != null) {
                    tax_rate = thisTax.getDouble("TOTAL_EFFECTIVE_TAX_RATE");
                }
            }

            LocalDate thisDate = getLocalDate(approveDate);//审批时间
            Double block_hour_multiplier = 0.0;
            if (thisContract != null && StringUtils.isNotBlank(ROLE_ID)) {
                //var thisConRole = new ctt_contract_rate_dal(_connect).GetSinRate(thisContract.id, (long)oldEntry.role_id);
                //return FindSignleBySql<ctt_contract_rate>($"SELECT * from ctt_contract_rate where delete_time = 0 and contract_id = {contract_id} and //role_id ={role_id}");
                RowMap thisConRole = DBSql.getMap("SELECT * FROM BO_EU_DNCTT_CONTRACT_RATE WHERE CONTRACT_ID=? AND ROLE_ID=?", new Object[]{thisContract.getString("ID"), ROLE_ID});

                if (thisConRole != null) {
                    block_hour_multiplier = thisConRole.getDouble("BLOCK_HOUR_MULTIPLIER");//乘数
                } else {
                    RowMap thisRole = DBSql.getMap("SELECT * FROM BO_EU_DNSYS_ROLE WHERE ID=?", new Object[]{ROLE_ID});
                    if (thisRole != null) {
                        block_hour_multiplier = thisRole.getDouble("HOURLY_FACTOR");//角色时间系数
                    }
                }
            }

            Map<String, Double> block = new HashMap<>();//存储预付id，和总价
            Map<String, Double> blockRate = new HashMap<>();//存储预付id，和总价

            RowMap thisWorkEntry = DBSql.getMap("select * from BO_EU_DNSDK_WORK_ENTRY where ID=?", new Object[]{getString(rowMap, "ID")});
            LocalDate thisEntryDate = getLocalDate(getString(thisWorkEntry, "START_TIME"));
            LocalDate thisEntryEndDate = StringUtils.isBlank(getString(thisWorkEntry, "START_TIME")) ? thisEntryDate : getLocalDate(getString(thisWorkEntry, "END_TIME"));

            LocalDate thisContractStartDate = thisContract == null ? null : thisContract.getDate("START_DATE").toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
            LocalDate thisContractEndDate = thisContract == null ? null : thisContract.getDate("END_DATE").toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();

            Double totalHours = StringUtils.isBlank(thisWorkEntry.getString("HOURS_BILLED_DEDUCTION")) ? thisWorkEntry.getDouble("HOURS_BILLED") : thisWorkEntry.getDouble("HOURS_BILLED_DEDUCTION");
            if (thisContract != null && thisEntryDate != null && thisContractStartDate.compareTo(thisEntryDate) <= 0 && thisContractEndDate.compareTo(thisEntryEndDate) >= 0) {

                String endDate = thisEntryDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

                // 这个工时的总额
                Double totalMoney = StringUtils.isBlank(thisWorkEntry.getString("HOURS_BILLED_DEDUCTION")) ? thisWorkEntry.getDouble("HOURS_BILLED") : thisWorkEntry.getDouble("HOURS_BILLED_DEDUCTION");
                totalMoney = totalMoney * (StringUtils.isBlank(thisWorkEntry.getString("HOURS_RATE_DEDUCTION")) ? laborRate : thisWorkEntry.getDouble("HOURS_RATE_DEDUCTION"));

                //不计费的工时
                if (laborRate == null || laborRate <= 0) {
                    BO thisBlockDed = new BO();
                    thisBlockDed.set("TYPE_ID", "1318");//工时
                    thisBlockDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                    thisBlockDed.set("POSTED_DATE", thisDate);
                    thisBlockDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                    thisBlockDed.set("ACCOUNT_ID", thisAccount.getString("ID"));
                    thisBlockDed.set("QUANTITY", totalHours);
                    thisBlockDed.set("BILL_CREATE_USER_ID", thisWorkEntry.getString("CREATEUSER"));
                    thisBlockDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                    thisBlockDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                    thisBlockDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                    thisBlockDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                    thisBlockDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                    thisBlockDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                    thisBlockDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                    if (thisTaxCate != null)
                        thisBlockDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("OID"));

                    thisBlockDed.set("EXTENDED_PRICE", 0);
                    thisBlockDed.set("BILL_ACCOUNT_ID", thisWorkEntry.get("BILL_ACCOUNT_ID"));


                    if (StringUtils.isBlank(thisBlockDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisBlockDed.getString("ACCOUNT_ID")))
                        thisBlockDed.set("BILL_ACCOUNT_ID", thisBlockDed.get("ACCOUNT_ID"));

                    dn.recordFormChanges.record(uc, thisBlockDed, "审批提交工时");
                    SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisBlockDed, uc);
                } else if (thisContract != null && thisContract.getString("TYPE_ID").equals("1203")) {
                    //预付费合同

                    //获取工时
                    Double extended_price = DBSql.getDouble("SELECT sum(round(b.rate/" + laborRate + " - ifnull((SELECT sum(extended_price)FROM bo_eu_dncrm_account_deduction WHERE contract_block_id = b.id ),0),2)) AS RATE FROM bo_eu_dnctt_contract_block b WHERE b.contract_id='" + thisContract.getString("ID") + "' and b.status_id=1 and b.start_date <='" + thisEntryDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "' and b.end_date >='" + endDate + "'", "RATE");
                    extended_price = extended_price * laborRate;

                    //  Double thisEntryRate = GetRateByCodeAndRole(COST_CODE_ID, ROLE_ID);

                    List<RowMap> block_hours = DBSql.getMaps("SELECT b.ID,(round(b.rate/" + laborRate + " - ifnull((SELECT sum(extended_price)FROM bo_eu_dncrm_account_deduction WHERE contract_block_id = b.id ),0),2)) AS RATE FROM bo_eu_dnctt_contract_block b WHERE b.contract_id='" + thisContract.getString("ID") + "' and b.status_id=1 and b.start_date <='" + thisEntryDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "' and b.end_date >='" + endDate + "'");

                    for (RowMap block_hour : block_hours) {
                        if (block_hour.get("RATE") != null && block_hour.getDouble("RATE") > 0) {
                            block.put(block_hour.getString("ID"), block_hour.getDouble("RATE"));
                        }
                        blockRate.put(block_hour.getString("ID"), block_hour.getDouble("RATE"));
                    }

                    if (totalMoney == null || totalMoney <= extended_price) {
                        if (totalMoney != null) {
                            Double extend = 0.0;
                            for (String key : block.keySet()) {
                                extend += block.get(key);
                                if (extend <= totalMoney) {
                                    BO thisBlockDed = new BO();
                                    thisBlockDed.set("TYPE_ID", "1318");
                                    thisBlockDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                                    thisBlockDed.set("POSTED_DATE", thisDate);
                                    thisBlockDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                                    thisBlockDed.set("EXTENDED_PRICE", block.get(key));
                                    thisBlockDed.set("ACCOUNT_ID", thisWorkEntry.getString("ACCOUNT_ID"));
                                    thisBlockDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                                    thisBlockDed.set("BILL_CREATE_USER_ID", thisWorkEntry.getString("CREATEUSER"));
                                    thisBlockDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                                    thisBlockDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                                    thisBlockDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                                    thisBlockDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                                    thisBlockDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                                    thisBlockDed.set("QUANTITY", totalHours);
                                    thisBlockDed.set("RATE", blockRate.get(key));
                                    thisBlockDed.set("CONTRACT_BLOCK_ID", key);
                                    thisBlockDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                                    thisBlockDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));

                                    if (thisTaxCate != null)
                                        thisBlockDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));


                                    if (thisAccount.getString("IS_TAX_EXEMPT").equals("1") == false) {
                                        thisBlockDed.set("TAX_DOLLARS", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * (1 - 1 / (1 + tax_rate)));
                                    }
                                    if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                                        thisBlockDed.set("EXTENDED_PRICE", 0);


                                    if (StringUtils.isBlank(thisBlockDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisBlockDed.getString("ACCOUNT_ID")))
                                        thisBlockDed.set("BILL_ACCOUNT_ID", thisBlockDed.get("ACCOUNT_ID"));

                                    dn.recordFormChanges.record(uc, thisBlockDed, "审批提交工时");
                                    SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisBlockDed, uc);

                                    //修改相应的预付费信息
                                    BO thisBlock = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_BLOCK", key);
                                    if (thisBlock != null) {
                                        thisBlock.set("STATUS_ID", 0);
                                        dn.recordFormChanges.record(uc, thisBlock, "修改预付费信息");
                                        SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_BLOCK", thisBlock);
                                    }
                                    if (extend == totalMoney) {
                                        break;
                                    }


                                } else {
                                    BO thisBlockDed = new BO();
                                    thisBlockDed.set("TYPE_ID", "1318");
                                    thisBlockDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                                    thisBlockDed.set("POSTED_DATE", thisDate);
                                    thisBlockDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                                    thisBlockDed.set("EXTENDED_PRICE", block.get(key));
                                    thisBlockDed.set("ACCOUNT_ID", thisWorkEntry.getString("ACCOUNT_ID"));
                                    thisBlockDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                                    thisBlockDed.set("BILL_CREATE_USER_ID", thisWorkEntry.getString("CREATEUSER"));
                                    thisBlockDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                                    thisBlockDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                                    thisBlockDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                                    thisBlockDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                                    thisBlockDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                                    thisBlockDed.set("QUANTITY", totalHours);
                                    thisBlockDed.set("RATE", blockRate.get(key));
                                    thisBlockDed.set("CONTRACT_BLOCK_ID", key);
                                    thisBlockDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                                    thisBlockDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                                    if (thisTaxCate != null)
                                        thisBlockDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));

                                    thisBlockDed.set("extended_price", block.get(key) - (extend - totalMoney));
                                    if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                                        thisBlockDed.set("EXTENDED_PRICE", 0);


                                    if (StringUtils.isBlank(thisBlockDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisBlockDed.getString("ACCOUNT_ID")))
                                        thisBlockDed.set("BILL_ACCOUNT_ID", thisBlockDed.get("ACCOUNT_ID"));

                                    dn.recordFormChanges.record(uc, thisBlockDed, "审批提交工时");
                                    SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisBlockDed, uc);
                                    break;
                                }
                            }
                        } else {

                            BO thisBlockDed = new BO();
                            thisBlockDed.set("TYPE_ID", "1318");
                            thisBlockDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                            thisBlockDed.set("POSTED_DATE", thisDate);
                            thisBlockDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                            thisBlockDed.set("ACCOUNT_ID", thisWorkEntry.getString("ACCOUNT_ID"));
                            thisBlockDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                            thisBlockDed.set("BILL_CREATE_USER_ID", thisWorkEntry.getString("CREATEUSER"));
                            thisBlockDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                            thisBlockDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                            thisBlockDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                            thisBlockDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                            thisBlockDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                            thisBlockDed.set("QUANTITY", totalHours);
                            thisBlockDed.set("RATE", thisWorkEntry.get("HOURS_RATE_DEDUCTION") != null ? thisWorkEntry.get("HOURS_RATE_DEDUCTION") : laborRate);
                            thisBlockDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                            thisBlockDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                            if (thisTaxCate != null)
                                thisBlockDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));
                            if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                                thisBlockDed.set("EXTENDED_PRICE", 0);


                            if (StringUtils.isBlank(thisBlockDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisBlockDed.getString("ACCOUNT_ID")))
                                thisBlockDed.set("BILL_ACCOUNT_ID", thisBlockDed.get("ACCOUNT_ID"));

                            dn.recordFormChanges.record(uc, thisBlockDed, "审批提交工时");
                            SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisBlockDed, uc);
                        }
                    } else {
                        RowMap ccnr = DBSql.getMap("select * from BO_EU_DNCTT_CONTRACT_NOTIFY_RULE where contract_id=?", new Object[]{thisContractId});
                        if (ccnr != null && ccnr.get("RATE") != null && ccnr.getDouble("RATE") > 0) {
                            Double extend = 0.0;
                            for (String key : block.keySet()) {
                                extend = extend + block.get(key);
                                BO thisBlockDed = new BO();
                                thisBlockDed.set("TYPE_ID", "1318");
                                thisBlockDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                                thisBlockDed.set("POSTED_DATE", thisDate);
                                thisBlockDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                                thisBlockDed.set("EXTENDED_PRICE", block.get(key));
                                thisBlockDed.set("ACCOUNT_ID", thisWorkEntry.getString("ACCOUNT_ID"));
                                thisBlockDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                                thisBlockDed.set("BILL_CREATE_USER_ID", thisWorkEntry.getString("CREATEUSER"));
                                thisBlockDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                                thisBlockDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                                thisBlockDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                                thisBlockDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                                thisBlockDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                                thisBlockDed.set("QUANTITY", totalHours);
                                thisBlockDed.set("RATE", blockRate.get(key));
                                thisBlockDed.set("CONTRACT_BLOCK_ID", key);
                                thisBlockDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                                thisBlockDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                                if (thisTaxCate != null)
                                    thisBlockDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));

                                if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                                    thisBlockDed.set("EXTENDED_PRICE", 0);

                                if (thisAccount.getString("IS_TAX_EXEMPT").equals("1") == false)
                                    thisBlockDed.set("TAX_DOLLARS", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * (1 - 1 / (1 + tax_rate)));

                                if (StringUtils.isBlank(thisBlockDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisBlockDed.getString("ACCOUNT_ID")))
                                    thisBlockDed.set("BILL_ACCOUNT_ID", thisBlockDed.get("ACCOUNT_ID"));

                                dn.recordFormChanges.record(uc, thisBlockDed, "审批提交工时");
                                SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisBlockDed, uc);

                                //修改相应的预付费信息
                                BO thisBlock = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_BLOCK", key);
                                if (thisBlock != null) {
                                    thisBlock.set("STATUS_ID", 0);
                                    dn.recordFormChanges.record(uc, thisBlock, "修改合同成本预付时间或费用");
                                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_BLOCK", thisBlock);
                                }
                            }

                            if (extend - totalMoney <= 0) {
                                //???  什么逻辑
                                System.out.println("合同金额不足");
                                System.out.println("后面怎么处理。。。。。。。。");
                            }


                        } else {
                            BO thisDed = new BO();
                            thisDed.set("TYPE_ID", "1318");
                            thisDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                            thisDed.set("POSTED_DATE", thisDate);
                            thisDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                            thisDed.set("EXTENDED_PRICE", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * block_hour_multiplier);
                            thisDed.set("ACCOUNT_ID", thisAccount.getString("ID"));
                            thisDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                            //thisDed.set("QUANTITY", thisWorkEntry.getDouble("HOURS_BILLED"));
                            thisDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                            thisDed.set("BILL_ACCOUNT_ID", thisWorkEntry.getString("BILL_ACCOUNT_ID"));
                            thisDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                            thisDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                            thisDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                            thisDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                            thisDed.set("QUANTITY", totalHours);
                            thisDed.set("RATE", thisWorkEntry.get("HOURS_RATE_DEDUCTION") != null ? thisWorkEntry.get("HOURS_RATE_DEDUCTION") : laborRate);
                            thisDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                            thisDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                            if (thisTaxCate != null)
                                thisDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));

                            if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                                thisDed.set("EXTENDED_PRICE", 0);

                            if (thisAccount.getString("IS_TAX_EXEMPT").equals("1") == false)
                                thisDed.set("TAX_DOLLARS", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * (1 - 1 / (1 + tax_rate)));

                            if (StringUtils.isBlank(thisDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisDed.getString("ACCOUNT_ID")))
                                thisDed.set("BILL_ACCOUNT_ID", thisDed.get("ACCOUNT_ID"));

                            dn.recordFormChanges.record(uc, thisDed, "审批提交工时");
                            SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisDed, uc);
                        }
                    }
                }
            }

            if (thisContract == null || (thisContract.getString("type_id").equals("1203") == false && thisContract.getString("TYPE_ID").equals("1202") == false) || thisContractStartDate.compareTo(thisEntryDate) > 0 || thisContractEndDate.compareTo(thisEntryEndDate) < 0) {
                BO thisDed = new BO();
                thisDed.set("TYPE_ID", "1318");
                thisDed.set("OBJECT_ID", thisWorkEntry.getString("ID"));
                thisDed.set("POSTED_DATE", thisDate);
                thisDed.set("TASK_ID", thisWorkEntry.getString("TASK_ID"));
                thisDed.set("EXTENDED_PRICE", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * block_hour_multiplier);
                thisDed.set("ACCOUNT_ID", thisAccount == null ? null : thisAccount.getString("ID"));
                thisDed.set("CONTRACT_ID", thisWorkEntry.getString("CONTRACT_ID"));
                //thisDed.set("QUANTITY", thisWorkEntry.getDouble("HOURS_BILLED"));
                thisDed.set("PURCHASE_ORDER_NO", thisWorkEntry.getString("PURCHASE_ORDER_NO"));
                thisDed.set("BILL_ACCOUNT_ID", thisWorkEntry.getString("BILL_ACCOUNT_ID"));
                thisDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
                thisDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
                thisDed.set("EFFECTIVE_TAX_RATE", tax_rate);
                thisDed.set("ROLE_ID", thisWorkEntry.getString("ROLE_ID"));
                thisDed.set("QUANTITY", totalHours);
                thisDed.set("RATE", thisWorkEntry.get("HOURS_RATE_DEDUCTION") != null ? thisWorkEntry.get("HOURS_RATE_DEDUCTION") : laborRate);
                thisDed.set("BLOCK_HOUR_MULTIPLIER", block_hour_multiplier);
                thisDed.set("EXTENDED_COST", GetEntryCost(thisWorkEntry.getString("ID")));
                if (thisTaxCate != null)
                    thisDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("ID"));

                if (thisWorkEntry.getString("IS_BILLABLE").equals("0"))
                    thisDed.set("EXTENDED_PRICE", 0);

                if (thisAccount.getString("IS_TAX_EXEMPT").equals("1") == false)
                    thisDed.set("TAX_DOLLARS", thisWorkEntry.getDouble("HOURS_BILLED") * laborRate * (1 - 1 / (1 + tax_rate)));

                if (StringUtils.isBlank(thisDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisDed.getString("ACCOUNT_ID")))
                    thisDed.set("BILL_ACCOUNT_ID", thisDed.get("ACCOUNT_ID"));

                dn.recordFormChanges.record(uc, thisDed, "审批提交工时");
                SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisDed, uc);
            }


            BO oldEntry = SDK.getBOAPI().get("BO_EU_DNSDK_WORK_ENTRY", thisWorkEntry.getString("ID"));
            oldEntry.set("APPROVE_AND_POST_DATE", thisDate);
            oldEntry.set("APPROVE_AND_POST_USER_ID", uc.getUID());
            dn.recordFormChanges.record(uc, oldEntry, "审批提交工时");
            SDK.getBOAPI().update("BO_EU_DNSDK_WORK_ENTRY", oldEntry);

            //通知
            // 待完善

        }

        return ResponseObject.newOkResponse();
    }

    /**
     * 获取字段值
     * @param rowMap
     * @param key
     * @return
     */
    private String getString(RowMap rowMap, String key) {
        if (rowMap.containsKey(key))
            return rowMap.getString(key);
        else if (rowMap.containsKey(key.toUpperCase()))
            return rowMap.getString(rowMap.getString(key.toUpperCase()));
        else if (rowMap.containsKey(key.toLowerCase()))
            return rowMap.getString(rowMap.getString(key.toLowerCase()));

        key = key.toUpperCase();
        for (String s : rowMap.keySet()) {
            if (s.toUpperCase().equals(key))
                return rowMap.getString(s);
        }
        return null;
    }


    /**
     * 费用审批
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.approve_expense")
    public ResponseObject expenseApprove(UserContext uc, String approveDate, String approveIds) {
        String[] IdArr = approveIds.split(",");
        String sql = "SELECT * FROM VIEW_EU_DNV_PENDING_EXPENSE WHERE ID IN(";
        for (int i = 0; IdArr.length > i; i++) {
            sql += "?,";
        }
        sql = sql.substring(0, sql.length() - 1) + ")";
        List<RowMap> list = DBSql.getMaps(sql, Arrays.stream(IdArr).toArray());
        for (RowMap rowMap : list) {
            String expenseId = getString(rowMap, "ID");
            RowMap oldExp = DBSql.getMap("SELECT * FROM BO_EU_DNSDK_EXPENSE WHERE ID=?", expenseId);
            RowMap thisTaxCate = null;//税收种类
            RowMap thisTaxRegion = null;//税区
            Double tax_rate = 0.0;//税率
            String contract_id = null;

            if (StringUtils.isNotBlank("COST_CODE_ID")) {
                RowMap thisCost = DBSql.getMap("SELECT * FROM BO_EU_DND_COST_CODE WHERE OID=? AND ORGID=?", new Object[]{getString(rowMap, "COST_CODE_ID"), uc.getCompanyModel().getId()});
                if (thisCost != null && StringUtils.isNotBlank(thisCost.getString("TAX_CATEGORY_ID"))) {
                    thisTaxCate = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=?  AND ORGID=?", new Object[]{thisCost.getString("TAX_CATEGORY_ID"), uc.getCompanyModel().getId()});
                }
            }


            RowMap thisAccount = DBSql.getMap("SELECT * FROM BO_EU_DNCRM_ACCOUNT WHERE ID=?", getString(rowMap, "ACCOUNT_ID"));
            if (thisAccount != null && StringUtils.isNotBlank(thisAccount.getString("TAX_REGION_ID"))) {
                thisTaxRegion = DBSql.getMap("SELECT * FROM BO_EU_DND_GENERAL WHERE OID=? AND ORGID=?", new Object[]{thisAccount.getString("TAX_REGION_ID"), uc.getCompanyModel().getId()});
            }


            if (thisTaxRegion != null && thisTaxCate != null) {
                tax_rate = DBSql.getDouble("SELECT TOTAL_EFFECTIVE_TAX_RATE FROM BO_EU_DND_TAX_REGION_CATE WHERE tax_region_id='" + thisTaxRegion.getString("OID") + "' and tax_cate_id='" + thisTaxCate.getString("OID") + "' and ORGID='" + uc.getCompanyModel().getId() + "'", "TOTAL_EFFECTIVE_TAX_RATE");
            }

            LocalDate thisDate = getLocalDate(approveDate);//审批时间

            if (StringUtils.isNotBlank(oldExp.getString("PROJECT_ID"))) {
                String projectRateContractId = DBSql.getString("SELECT CONTRACT_ID FROM BO_EU_DNPRO_PROJECT WHERE ID=?", new Object[]{oldExp.getString("PROJECT_ID")});
                if (StringUtils.isNotBlank(projectRateContractId)) {
                    contract_id = projectRateContractId;
                }
            }

            if (StringUtils.isNotBlank(oldExp.getString("TASK_ID"))) {
                String taskRateContractId = DBSql.getString("SELECT CONTRACT_ID FROM BO_EU_DNSDK_TASK WHERE ID=?", new Object[]{oldExp.getString("TASK_ID")});
                if (StringUtils.isNotBlank(taskRateContractId)) {
                    contract_id = taskRateContractId;
                }
            }


            Double extended_price = 0.0;
            if (oldExp.getString("IS_BILLABLE").equals("1")) {
                if (oldExp.get("AMOUNT_DEDUCTION") != null && oldExp.getDouble("AMOUNT_DEDUCTION") > 0) {
                    extended_price = oldExp.getDouble("AMOUNT_DEDUCTION");
                } else if (oldExp.get("AMOUNT") != null && oldExp.getDouble("AMOUNT") > 0) {
                    extended_price = oldExp.getDouble("AMOUNT");
                }
            }

            BO thisDed = new BO();
            thisDed.set("CONTRACT_ID", contract_id);
            thisDed.set("OBJECT_ID", oldExp.getString("ID"));
            thisDed.set("TYPE_ID", "1322");
            thisDed.set("POSTED_DATE", thisDate);
            thisDed.set("TASK_ID", oldExp.getString("TASK_ID"));
            thisDed.set("EXTENDED_PRICE", extended_price);
            thisDed.set("EXTENDED_COST", extended_price);
            thisDed.set("ACCOUNT_ID", oldExp.getString("ACCOUNT_ID"));
            thisDed.set("QUANTITY", 1);
            thisDed.set("BILL_CREATE_USER_ID", oldExp.getString("CREATEUSER"));
            thisDed.set("PURCHASE_ORDER_NO", oldExp.getString("PURCHASE_ORDER_NO"));
            thisDed.set("TAX_CATEGORY_NAME", thisTaxCate == null ? null : thisTaxCate.getString("NAME"));
            thisDed.set("TAX_REGION_NAME", thisTaxRegion == null ? null : thisTaxRegion.getString("NAME"));
            thisDed.set("EFFECTIVE_TAX_RATE", tax_rate);

            if ((thisAccount == null || !thisAccount.getString("IS_TAX_EXEMPT").equals("1")) && tax_rate > 0) {
                thisDed.set("TAX_DOLLARS", extended_price * (1 - 1 / (1 + tax_rate)));
            }

            if (thisTaxCate != null)
                thisDed.set("TAX_CATEGORY_ID", thisTaxCate.getString("OID"));

            if (StringUtils.isBlank(thisDed.getString("BILL_ACCOUNT_ID")) && StringUtils.isNotBlank(thisDed.getString("ACCOUNT_ID")))
                thisDed.set("BILL_ACCOUNT_ID", thisDed.get("ACCOUNT_ID"));

            dn.recordFormChanges.record(uc, thisDed, "审批提交费用");
            SDK.getBOAPI().createDataBO("BO_EU_DNCRM_ACCOUNT_DEDUCTION", thisDed, uc);

            BO oldExpense = SDK.getBOAPI().get("BO_EU_DNSDK_EXPENSE", oldExp.getString("ID"));
            oldExpense.set("APPROVE_AND_POST_DATE", thisDate);
            oldExpense.set("APPROVE_AND_POST_USER_ID", uc.getUID());
            dn.recordFormChanges.record(uc, oldExpense, "审批提交费用");
            SDK.getBOAPI().update("BO_EU_DNSDK_EXPENSE", oldExpense);


            //通知
        }


        return ResponseObject.newOkResponse();
    }


    /**
     * 撤销工时审批
     * @param ids
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_labor")
    public ResponseObject revokeLabor(UserContext uc, String ids) throws SQLException {
        Connection connUpdate = null;
        try {
            connUpdate = DBSql.open();
            connUpdate.setAutoCommit(false);
            for (String id : ids.split(",")) {
                BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
                bo.set("CLOSED", 1);
                dn.recordFormChanges.record(uc, bo, "撤销工时审批");

                SDK.getBOAPI().remove("BO_EU_DNCRM_ACCOUNT_DEDUCTION", bo.getId(), connUpdate);

                BO oldEntry = SDK.getBOAPI().get("BO_EU_DNSDK_WORK_ENTRY", bo.getString("OBJECT_ID"));
                oldEntry.set("APPROVE_AND_POST_DATE", null);
                oldEntry.set("APPROVE_AND_POST_USER_ID", null);
                dn.recordFormChanges.record(uc, oldEntry, "撤销工时审批");
                SDK.getBOAPI().update("BO_EU_DNSDK_WORK_ENTRY", oldEntry);

            }
            connUpdate.commit();
        } catch (SQLException e) {
            if (connUpdate != null && !connUpdate.isClosed())
                try {
                    connUpdate.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
        } finally {
            if (connUpdate != null && !connUpdate.isClosed())
                DBSql.close(connUpdate);
        }
        return ResponseObject.newOkResponse();
    }


    /**
     * 撤销费用审批
     * @param uc
     * @param ids
     * @return
     * @throws SQLException
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_expense")
    public ResponseObject revokeExpense(UserContext uc, String ids) throws SQLException {
        Connection connUpdate = null;
        try {
            connUpdate = DBSql.open();
            connUpdate.setAutoCommit(false);
            for (String id : ids.split(",")) {
                BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
                bo.set("CLOSED", 1);
                dn.recordFormChanges.record(uc, bo, "撤销费用审批");

                SDK.getBOAPI().remove("BO_EU_DNCRM_ACCOUNT_DEDUCTION", bo.getId(), connUpdate);

                BO oldEntry = SDK.getBOAPI().get("BO_EU_DNSDK_EXPENSE", bo.getString("OBJECT_ID"));
                oldEntry.set("APPROVE_AND_POST_DATE", null);
                oldEntry.set("APPROVE_AND_POST_USER_ID", null);
                dn.recordFormChanges.record(uc, oldEntry, "撤销费用审批");
                SDK.getBOAPI().update("BO_EU_DNSDK_EXPENSE", oldEntry);

            }
            connUpdate.commit();
        } catch (SQLException e) {
            if (connUpdate != null && !connUpdate.isClosed())
                try {
                    connUpdate.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
        } finally {
            if (connUpdate != null && !connUpdate.isClosed())
                DBSql.close(connUpdate);
        }
        return ResponseObject.newOkResponse();
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.updateCommissionPeriodEndDate")
    public ResponseObject updateCommissionPeriodEndDate(UserContext uc, String id, String periodEndDate) {
        // 1. 参数校验
        if (StringUtils.isBlank(id)) {
            return ResponseObject.newErrResponse("id 不能为空");
        }
        if (StringUtils.isBlank(periodEndDate)) {
            return ResponseObject.newErrResponse("PERIOD_END_DATE 不能为空");
        }

        try {

            // 3. 构建更新 SQL
            String updateSql = "UPDATE BO_EU_DNCTT_COMMISSION SET PERIOD_END_DATE = ? WHERE ID = ?";

            // 4. 执行更新操作
            int rows = DBSql.update(updateSql, new Object[]{periodEndDate, id});

            // 5. 构造返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("id", id);
            result.put("periodEndDate", periodEndDate);
            result.put("updatedRows", rows);

            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);

            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("更新失败：" + e.getMessage());
        }
    }

    // 按月补贴：周期增量=1个月
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.insertMonthlyCommission")
    public ResponseObject insertMonthlyCommission(UserContext uc,
                                                  String bindid,
                                                  String startDate,
                                                  String endDate,
                                                  String amount) {
        return insertCommissionByPeriod(uc, bindid, startDate, endDate, amount, 1);
    }

    // 按季度补贴：周期增量=3个月
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.insertQuarterlyCommission")
    public ResponseObject insertQuarterlyCommission(UserContext uc,
                                                    String bindid,
                                                    String startDate,
                                                    String endDate,
                                                    String amount) {
        return insertCommissionByPeriod(uc, bindid, startDate, endDate, amount, 3);
    }

    // 按年补贴：周期增量=12个月
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.insertYearlyCommission")
    public ResponseObject insertYearlyCommission(UserContext uc,
                                                 String bindid,
                                                 String startDate,
                                                 String endDate,
                                                 String amount) {
        return insertCommissionByPeriod(uc, bindid, startDate, endDate, amount, 12);
    }

    // 一次性补贴：只生成一个周期（开始日期到结束日期）
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.insertOneTimeCommission")
    public ResponseObject insertOneTimeCommission(UserContext uc,
                                                  String bindid,
                                                  String startDate,
                                                  String endDate,
                                                  String amount) {
        // 1. 参数校验
        if (StringUtils.isBlank(bindid)) return ResponseObject.newErrResponse("bindid不能为空");
        if (StringUtils.isBlank(startDate)) return ResponseObject.newErrResponse("开始日期不能为空");
        if (StringUtils.isBlank(endDate)) return ResponseObject.newErrResponse("结束日期不能为空");
        if (StringUtils.isBlank(amount)) return ResponseObject.newErrResponse("金额不能为空");

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            // 校验开始日期是否早于结束日期
            Date start = sdf.parse(startDate);
            Date end = sdf.parse(endDate);
            if (start.after(end)) {
                return ResponseObject.newErrResponse("开始日期不能晚于结束日期");
            }

            // 2. 插入SQL（仅插入一条记录）
            String insertSql = "INSERT INTO BO_EU_DNCTT_COMMISSION_PERIOD " +
                    "(ID, ORGID, BINDID, PERIOD_BEGIN_DATE, PERIOD_END_DATE, " +
                    "COMMISSION_DOLLARS, PERIOD_ADJUSTED_PRICE) " +
                    "VALUES (UUID(), ?, ?, ?, ?, ?, ?)";

            // 3. 执行插入（仅一次，不循环）
            int rows = DBSql.update(insertSql, new Object[]{
                    uc.getCompanyModel().getId(),
                    bindid,
                    startDate, // 直接用用户输入的开始日期
                    endDate,   // 直接用用户输入的结束日期
                    amount,
                    amount
            });

            // 4. 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("bindid", bindid);
            result.put("rows", rows); // 应为1（成功插入1条）
            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);

            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("插入失败：" + e.getMessage());
        }
    }

    // 通用方法：按周期增量（1/3/12个月）生成多个周期
    private ResponseObject insertCommissionByPeriod(UserContext uc,
                                                    String bindid,
                                                    String startDate,
                                                    String endDate,
                                                    String amount,
                                                    int periodIncrement) {
        // 参数校验（同上，略）
        if (StringUtils.isBlank(bindid)) return ResponseObject.newErrResponse("bindid不能为空");
        // ... 其他校验

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar cal = Calendar.getInstance();
            cal.setTime(sdf.parse(startDate));
            int settleDay = cal.get(Calendar.DATE); // 固定结算日

            Calendar endCal = Calendar.getInstance();
            endCal.setTime(sdf.parse(endDate));

            String insertSql = "INSERT INTO BO_EU_DNCTT_COMMISSION_PERIOD " +
                    "(ID, ORGID, BINDID, PERIOD_BEGIN_DATE, PERIOD_END_DATE, " +
                    "COMMISSION_DOLLARS, PERIOD_ADJUSTED_PRICE) " +
                    "VALUES (UUID(), ?, ?, ?, ?, ?, ?)";

            int rows = 0;
            Calendar currentCal = Calendar.getInstance();
            currentCal.setTime(sdf.parse(startDate));

            // 循环生成周期（按传入的增量：1/3/12个月）
            while (true) {
                Date periodStart = currentCal.getTime();
                if (periodStart.after(endCal.getTime())) break;

                currentCal.add(Calendar.MONTH, periodIncrement);
                currentCal.set(Calendar.DATE, settleDay);
                currentCal.add(Calendar.DATE, -1);
                Date periodEnd = currentCal.getTime();

                if (periodEnd.after(endCal.getTime())) periodEnd = endCal.getTime();

                rows += DBSql.update(insertSql, new Object[]{
                        uc.getCompanyModel().getId(),
                        bindid,
                        sdf.format(periodStart),
                        sdf.format(periodEnd),
                        amount,
                        amount
                });

                currentCal.add(Calendar.DATE, 1);
                currentCal.set(Calendar.DATE, settleDay);
            }

            Map<String, Object> result = new HashMap<>();
            result.put("rows", rows);
            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);

            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("插入失败：" + e.getMessage());
        }
    }

    // 通用查询代理列表（不变）
    private List<Map<String, Object>> queryAgentList(String bindid) {
        List<Map<String, Object>> agentList = new ArrayList<>();
        int offset = 0;
        while (true) {
            String querySql = "SELECT AGENT, RATIO FROM BO_EU_DNCTT_COMMISSION_AGENT WHERE bindid = ? LIMIT 1 OFFSET ?";
            RowMap agentMap = DBSql.getMap(querySql, new Object[]{bindid, offset});
            if (agentMap == null) break;

            String agent = agentMap.getString("AGENT");
            BigDecimal ratio = parseRatio(agentMap.get("RATIO"));
            if (ratio == null) {
                throw new RuntimeException("代理 " + agent + " 的比例为空");
            }

            Map<String, Object> agentInfo = new HashMap<>();
            agentInfo.put("AGENT", agent);
            agentInfo.put("RATIO", ratio);
            agentList.add(agentInfo);
            offset++;
        }
        return agentList;
    }

    // 通用比例解析（不变）
    private BigDecimal parseRatio(Object ratioObj) {
        if (ratioObj == null) return null;
        try {
            if (ratioObj instanceof BigDecimal) return (BigDecimal) ratioObj;
            if (ratioObj instanceof Double) return BigDecimal.valueOf((Double) ratioObj);
            if (ratioObj instanceof Float) return BigDecimal.valueOf(((Float) ratioObj).doubleValue());
            if (ratioObj instanceof Integer) return BigDecimal.valueOf(((Integer) ratioObj).longValue());
            return new BigDecimal(ratioObj.toString());
        } catch (Exception e) {
            throw new RuntimeException("比例格式错误：" + ratioObj, e);
        }
    }

    // 通用周期生成方法（按月/季度/年复用，不变）
    private ResponseObject batchInsertAgentByPeriod(UserContext uc,
                                                    String bindid,
                                                    String startDate,
                                                    String endDate,
                                                    String amount,
                                                    int periodIncrement) {
        try {
            // 参数校验
            if (StringUtils.isBlank(bindid) || StringUtils.isBlank(startDate) ||
                    StringUtils.isBlank(endDate) || StringUtils.isBlank(amount)) {
                return ResponseObject.newErrResponse("bindid、日期、金额不能为空");
            }

            // 查询代理列表
            List<Map<String, Object>> agentList = queryAgentList(bindid);
            if (agentList.isEmpty()) {
                return ResponseObject.newErrResponse("未找到二级代理数据");
            }

            // 日期与金额处理
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar cal = Calendar.getInstance();
            cal.setTime(sdf.parse(startDate));
            int settleDay = cal.get(Calendar.DATE);
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(sdf.parse(endDate));
            BigDecimal baseAmount = new BigDecimal(amount);

            // 插入SQL
            String insertSql = "INSERT INTO BO_EU_DNCTT_COMMISSION_PERIOD_AGENT " +
                    "(ID, AGENT, ORGID, BINDID, PERIOD_BEGIN_DATE, PERIOD_END_DATE, " +
                    "COMMISSION_DOLLARS, PERIOD_ADJUSTED_PRICE) " +
                    "VALUES (UUID(), ?, ?, ?, ?, ?, ?, ?)";

            int totalRows = 0;
            for (Map<String, Object> agentInfo : agentList) {
                String agent = (String) agentInfo.get("AGENT");
                BigDecimal ratio = (BigDecimal) agentInfo.get("RATIO");
                BigDecimal realCommission = baseAmount.multiply(ratio.divide(new BigDecimal("100")));

                // 按周期增量生成子周期
                Calendar currentCal = Calendar.getInstance();
                currentCal.setTime(sdf.parse(startDate));
                while (true) {
                    Date periodStart = currentCal.getTime();
                    if (periodStart.after(endCal.getTime())) break;

                    // 计算周期结束日
                    currentCal.add(Calendar.MONTH, periodIncrement);
                    currentCal.set(Calendar.DATE, settleDay);
                    currentCal.add(Calendar.DATE, -1);
                    Date periodEnd = currentCal.getTime();
                    if (periodEnd.after(endCal.getTime())) periodEnd = endCal.getTime();

                    // 插入记录
                    totalRows += DBSql.update(insertSql, new Object[]{
                            agent, uc.getCompanyModel().getId(), bindid,
                            sdf.format(periodStart), sdf.format(periodEnd),
                            realCommission.toPlainString(), realCommission.toPlainString()
                    });

                    // 准备下一个周期
                    currentCal.add(Calendar.DATE, 1);
                    currentCal.set(Calendar.DATE, settleDay);
                }
            }

            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("bindid", bindid);
            result.put("rows", totalRows);
            result.put("agentCount", agentList.size());
            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("插入失败：" + e.getMessage());
        }
    }

    // 1. 按月生成（周期增量=1个月）
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.batchInsertAgentMonthly")
    public ResponseObject batchInsertAgentMonthly(UserContext uc,
                                                  String bindid,
                                                  String startDate,
                                                  String endDate,
                                                  String amount) {
        return batchInsertAgentByPeriod(uc, bindid, startDate, endDate, amount, 1);
    }

    // 2. 按季度生成（周期增量=3个月）
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.batchInsertAgentQuarterly")
    public ResponseObject batchInsertAgentQuarterly(UserContext uc,
                                                    String bindid,
                                                    String startDate,
                                                    String endDate,
                                                    String amount) {
        return batchInsertAgentByPeriod(uc, bindid, startDate, endDate, amount, 3);
    }

    // 3. 按年生成（新增，周期增量=12个月）
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.batchInsertAgentYearly")
    public ResponseObject batchInsertAgentYearly(UserContext uc,
                                                 String bindid,
                                                 String startDate,
                                                 String endDate,
                                                 String amount) {
        return batchInsertAgentByPeriod(uc, bindid, startDate, endDate, amount, 12); // 12个月=1年
    }

    // 4. 一次性生成（无周期拆分）
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.batchInsertAgentOneTime")
    public ResponseObject batchInsertAgentOneTime(UserContext uc,
                                                  String bindid,
                                                  String startDate,
                                                  String endDate,
                                                  String amount) {
        try {
            // 参数校验
            if (StringUtils.isBlank(bindid) || StringUtils.isBlank(startDate) ||
                    StringUtils.isBlank(endDate) || StringUtils.isBlank(amount)) {
                return ResponseObject.newErrResponse("bindid、日期、金额不能为空");
            }

            // 日期合法性校验
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date start = sdf.parse(startDate);
            Date end = sdf.parse(endDate);
            if (start.after(end)) {
                return ResponseObject.newErrResponse("开始日期不能晚于结束日期");
            }

            // 查询代理列表
            List<Map<String, Object>> agentList = queryAgentList(bindid);
            if (agentList.isEmpty()) {
                return ResponseObject.newErrResponse("未找到二级代理数据");
            }

            // 插入SQL
            String insertSql = "INSERT INTO BO_EU_DNCTT_COMMISSION_PERIOD_AGENT " +
                    "(ID, AGENT, ORGID, BINDID, PERIOD_BEGIN_DATE, PERIOD_END_DATE, " +
                    "COMMISSION_DOLLARS, PERIOD_ADJUSTED_PRICE) " +
                    "VALUES (UUID(), ?, ?, ?, ?, ?, ?, ?)";

            int totalRows = 0;
            BigDecimal baseAmount = new BigDecimal(amount);
            for (Map<String, Object> agentInfo : agentList) {
                String agent = (String) agentInfo.get("AGENT");
                BigDecimal ratio = (BigDecimal) agentInfo.get("RATIO");
                BigDecimal realCommission = baseAmount.multiply(ratio.divide(new BigDecimal("100")));

                // 直接插入“开始→结束”的1条记录
                totalRows += DBSql.update(insertSql, new Object[]{
                        agent, uc.getCompanyModel().getId(), bindid,
                        startDate, endDate,
                        realCommission.toPlainString(), realCommission.toPlainString()
                });
            }

            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("bindid", bindid);
            result.put("rows", totalRows);
            result.put("agentCount", agentList.size());
            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("插入失败：" + e.getMessage());
        }
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.checkCommissionPeriodExists2")
    public ResponseObject checkCommissionPeriodExists2(UserContext uc,
                                                      String bindid,
                                                      String startDate,
                                                      String endDate) {
        try {
            String checkSql = "SELECT COUNT(1) FROM BO_EU_DNCTT_COMMISSION_PERIOD " +
                    "WHERE BINDID = ? " +
                    "AND PERIOD_BEGIN_DATE <= ? " +
                    "AND PERIOD_END_DATE >= ?";

            int existCount = DBSql.getInt(checkSql, new Object[]{bindid, endDate, startDate});

            Map<String, Object> result = new HashMap<>();
            result.put("exists", existCount > 0);

            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("查询失败：" + e.getMessage());
        }
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.checkAgentCommissionPeriodExists")
    public ResponseObject checkAgentCommissionPeriodExists(UserContext uc,
                                                           String bindid,
                                                           String startDate,
                                                           String endDate) {
        try {
            String checkSql = "SELECT COUNT(1) FROM BO_EU_DNCTT_COMMISSION_PERIOD_AGENT " +
                    "WHERE BINDID = ?";

            int existCount = DBSql.getInt(checkSql, new Object[]{bindid});

            Map<String, Object> result = new HashMap<>();
            result.put("exists", existCount > 0);

            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("查询失败：" + e.getMessage());
        }
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.updateAgentCommissionByIds")
    public ResponseObject updateAgentCommissionByIds(UserContext uc,
                                                     String ids,
                                                     String commissionPayId,
                                                     String agent,
                                                     String ACCOUNT_PAY_DATE,
                                                     BigDecimal payAmount,
                                                     String payer,
                                                     String remark,
                                                     String invoiceTypeId,
                                                     String agentInvoiceNo,
                                                     String invoiceFile) {
        try {
            if (ids == null || ids.trim().isEmpty()) {
                return ResponseObject.newErrResponse("ids不能为空");
            }
            if (commissionPayId == null || commissionPayId.trim().isEmpty()) {
                return ResponseObject.newErrResponse("commissionPayId不能为空");
            }

            String[] idArr = ids.split(",");

            StringBuilder updateSql = new StringBuilder("UPDATE VIEW_EU_DNV_COMMISSION_PERIOD_AGENT SET ");
            List<Object> params = new ArrayList<>();

            updateSql.append("COMMISSION_PAY_ID = ?, AGENT = ?, ACCOUNT_PAY_DATE = ?, PAY_AMOUNT = ?, PAYER = ?, ");
            params.add(commissionPayId.trim());
            params.add(agent);
            params.add(ACCOUNT_PAY_DATE);
            params.add(payAmount);
            params.add(payer);

            // 可选字段
            if (remark != null && !remark.trim().isEmpty()) {
                updateSql.append("REMARK = ?, ");
                params.add(remark);
            }
            if (invoiceTypeId != null && !invoiceTypeId.trim().isEmpty()) {
                updateSql.append("INVOICE_TYPE_ID = ?, ");
                params.add(invoiceTypeId);
            }
            if (agentInvoiceNo != null && !agentInvoiceNo.trim().isEmpty()) {
                updateSql.append("AGENT_INVOICE_NO = ?, ");
                params.add(agentInvoiceNo);
            }
            if (invoiceFile != null && !invoiceFile.trim().isEmpty()) {
                updateSql.append("INVOICE_FILE = ?, ");
                params.add(invoiceFile);
            }

            if (updateSql.charAt(updateSql.length() - 2) == ',') {
                updateSql.setLength(updateSql.length() - 2);
            }

            StringBuilder placeholders = new StringBuilder();
            for (int i = 0; i < idArr.length; i++) {
                if (i > 0) placeholders.append(",");
                placeholders.append("?");
            }
            updateSql.append(" WHERE ID IN (").append(placeholders.toString()).append(")");

            for (String id : idArr) {
                params.add(id.trim());
            }

            int updateCount = DBSql.update(updateSql.toString(), params.toArray());

            Map<String, Object> result = new HashMap<>();
            result.put("updateCount", updateCount);

            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseObject.newErrResponse("更新失败：" + e.getMessage());
        }
    }

    /**
     * 佣金审批
     * @param uc
     * @param approveDate
     * @param approveIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.approve_commission")
    public ResponseObject approveCommission(UserContext uc, String approveDate, String approveIds) throws SQLException {
        if (StringUtils.isBlank(approveDate) || StringUtils.isBlank(approveIds))
            return ResponseObject.newErrResponse("参数错误");
        contractService.getInstance().approveCommission(uc, approveDate, approveIds);
        return ResponseObject.newOkResponse();
    }


    /**
     * 佣金调整
     * @param uc
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.approve_updateCommissionPrice")
    public ResponseObject updateCommissionPrice(UserContext uc, String id, String periodPrice) {
/*
        BO bo = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD", id);//佣金

        String APPROVE_AND_POST_DATE = bo.getString("APPROVE_AND_POST_DATE");
        System.out.println("APPROVE_AND_POST_DATE------------" + APPROVE_AND_POST_DATE);
        if (StringUtils.isNotBlank(APPROVE_AND_POST_DATE))
            return ResponseObject.newErrResponse("已审批不允许修改");

        bo.set("PERIOD_ADJUSTED_PRICE", periodPrice);
        SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD", bo);
*/
        RowMap period = DBSql.getMap("select * from BO_EU_DNCTT_COMMISSION_PERIOD where ID=?", new Object[]{id});
        String APPROVE_AND_POST_DATE = period.getString("APPROVE_AND_POST_DATE");
        System.out.println("APPROVE_AND_POST_DATE------------" + APPROVE_AND_POST_DATE);
        if (StringUtils.isNotBlank(APPROVE_AND_POST_DATE))
            return ResponseObject.newErrResponse("已审批不允许修改");

        DBSql.update("update BO_EU_DNCTT_COMMISSION_PERIOD set PERIOD_ADJUSTED_PRICE=? where ID=?", new Object[]{periodPrice, id});

        return ResponseObject.newOkResponse();
    }


    /**
     * 佣金调整，恢复初始价格
     * @param uc
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.approve_initCommissionPrice")
    public ResponseObject initCommissionPrice(UserContext uc, String ids) {

        for (String id : ids.split(",")) {
            /*
            BO bo = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD", id);//佣金

            String APPROVE_AND_POST_DATE = bo.getString("APPROVE_AND_POST_DATE");
            System.out.println("APPROVE_AND_POST_DATE------------" + APPROVE_AND_POST_DATE);
            if (StringUtils.isNotBlank(APPROVE_AND_POST_DATE))
                return ResponseObject.newErrResponse("已审批不允许修改");

            bo.set("PERIOD_ADJUSTED_PRICE", bo.get("COMMISSION_DOLLARS"));
            SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD", bo);

             */

            RowMap period = DBSql.getMap("select * from BO_EU_DNCTT_COMMISSION_PERIOD where ID=?", new Object[]{id});
            String APPROVE_AND_POST_DATE = period.getString("APPROVE_AND_POST_DATE");
            System.out.println("APPROVE_AND_POST_DATE------------" + APPROVE_AND_POST_DATE);
            if (StringUtils.isNotBlank(APPROVE_AND_POST_DATE))
                return ResponseObject.newErrResponse("已审批不允许修改");

            DBSql.update("update BO_EU_DNCTT_COMMISSION_PERIOD set PERIOD_ADJUSTED_PRICE=COMMISSION_DOLLARS where ID=?", new Object[]{id});

        }

        return ResponseObject.newOkResponse();
    }


    /**
     * 撤销佣金审批
     * @param ids
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_commission")
    public ResponseObject revokeCommission(UserContext uc, String ids) throws SQLException {
        Connection connUpdate = null;
        try {
            connUpdate = DBSql.open();
            connUpdate.setAutoCommit(false);
            for (String id : ids.split(",")) {
                BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
                bo.set("CLOSED", 1);
                dn.recordFormChanges.record(uc, bo, "撤销佣金审批");

                SDK.getBOAPI().remove("BO_EU_DNCRM_ACCOUNT_DEDUCTION", bo.getId(), connUpdate);

                /*
                BO oldEntry = SDK.getBOAPI().get("BO_EU_DNCTT_COMMISSION_PERIOD", bo.getString("OBJECT_ID"));
                oldEntry.set("APPROVE_AND_POST_DATE", null);
                oldEntry.set("APPROVE_AND_POST_USER_ID", null);
                dn.recordFormChanges.record(uc, oldEntry, "撤销佣金审批");
                SDK.getBOAPI().update("BO_EU_DNCTT_COMMISSION_PERIOD", oldEntry);

                 */
                DBSql.update("update BO_EU_DNCTT_COMMISSION_PERIOD set APPROVE_AND_POST_DATE=null,APPROVE_AND_POST_USER_ID=null where ID=?", new Object[]{bo.getString("OBJECT_ID")});

            }
            connUpdate.commit();
        } catch (SQLException e) {
            if (connUpdate != null && !connUpdate.isClosed())
                try {
                    connUpdate.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
        } finally {
            if (connUpdate != null && !connUpdate.isClosed())
                DBSql.close(connUpdate);
        }
        return ResponseObject.newOkResponse();
    }

    @Mapping("com.awspaas.user.apps.donenow_ctt.matchBillByHeadquartersFeePeriod2")
    public ResponseObject matchBillByHeadquartersFeePeriod2(UserContext uc, String headquartersFeePeriod) throws SQLException {
        Connection connUpdate = null;
        try {
            // 参数校验（不变）
            if (StringUtils.isBlank(headquartersFeePeriod)) {
                return ResponseObject.newErrResponse("总部费用账期不能为空");
            }
            String feePeriod = headquartersFeePeriod.trim();

            // 1. 查询需要更新的数据：新增查询a表ID（a.ID AS a_id）
            String querySql = "SELECT " +
                    "a.ID AS a_id, " + // 【修改1：新增查询a表ID，用于存到c表COMMISSION_IMPORT_ID】
                    "a.COMMISSION_DOLLARS AS 佣金, " +
                    "a.TOTAL_DOLLARS AS 基数, " +
                    "a.RATIO AS 比例, " +
                    "a.ZB_BILLING_DATE AS 账单日期, " +
                    "c.ID AS c_id  " +
                    "FROM BO_EU_DNCTT_COMMISSION_IMPORT a " +
                    "JOIN BO_EU_DNCTT_COMMISSION b " +
                    "ON a.ACCOUNT_NO = b.NEW_ACCOUNT AND a.DEVICE_ID = b.DEVICE_ID " +
                    "JOIN BO_EU_DNCTT_COMMISSION_PERIOD c " +
                    "ON a.ZB_FEE_DATE = c.ZB_FEE_DATE AND b.bindid = c.bindid " +
                    "WHERE a.ZB_FEE_DATE = ?";

            List<RowMap> matchRecords = DBSql.getMaps(querySql, new Object[]{feePeriod});

            if (matchRecords == null || matchRecords.isEmpty()) {
                Map<String, Object> result = new HashMap<>();
                result.put("totalMatched", 0);
                result.put("message", "未找到对应账期的记录");
                ResponseObject responseObject = ResponseObject.newOkResponse();
                responseObject.setData(result);
                return responseObject;
            }

            // 2. 初始化连接 + 事务控制（不变）
            connUpdate = DBSql.open();
            connUpdate.setAutoCommit(false);

            int updateCount = 0;

            // 3. 循环处理每条记录
            for (RowMap record : matchRecords) {
                // 键值处理（不变）
                for (String key : record.keySet()) {
                    record.put(key.toUpperCase(), record.get(key) == null ? "" : record.get(key));
                }

                // 【修改2：提取a表ID（a_id），用于更新到c表COMMISSION_IMPORT_ID】
                String aId = record.getString("a_id"); // 从查询结果中获取a表ID

                // 提取c表ID（不变）
                String cId = record.getString("c_id");
                if (StringUtils.isBlank(cId)) {
                    System.out.println("跳过无c表ID的记录：" + record);
                    continue;
                }

                // 提取其他字段（不变）
                Double commission = record.getDouble("佣金");
                Double total = record.getDouble("基数");
                String ratioStr = record.getString("比例");
                String zbBillingDate = record.getString("账单日期");

                // 处理比例字段（不变）
                Double ratio = 0.0;
                if (StringUtils.isNotBlank(ratioStr)) {
                    String pureRatio = ratioStr.replace("%", "").trim();
                    if ((StringUtils.isNumeric(pureRatio) || pureRatio.contains("."))) {
                        try {
                            ratio = Double.parseDouble(pureRatio);
                        } catch (NumberFormatException e) {
                            System.out.println("比例格式错误（使用默认值0.0）：" + ratioStr);
                        }
                    } else {
                        System.out.println("比例非数字（使用默认值0.0）：" + ratioStr);
                    }
                }

                // 4. 执行更新：新增COMMISSION_IMPORT_ID字段的更新
                DBSql.update(connUpdate,
                        "UPDATE BO_EU_DNCTT_COMMISSION_PERIOD " +
                                "SET COMMISSION_DOLLARS = ?, " +
                                "TOTAL_DOLLARS_IMPORT = ?, " +
                                "RATIO_IMPORT = ?, " +
                                "ZB_BILLING_DATE = ?, " +
                                "COMMISSION_IMPORT_ID = ? " + // 【修改3：新增字段，存a表ID】
                                "WHERE ID = ?",
                        new Object[]{
                                commission,   // 1. 佣金
                                total,        // 2. 基数
                                ratio,        // 3. 处理后的比例
                                zbBillingDate,// 4. 账单日期
                                aId,          // 5. 【修改4：新增参数，传入a表ID】
                                cId           // 6. 条件：c表ID
                        }
                );

                updateCount++;
            }

            // 5. 提交事务（不变）
            connUpdate.commit();

            // 6. 响应结果（不变）
            Map<String, Object> result = new HashMap<>();
            result.put("totalMatched", matchRecords.size());
            result.put("updateCount", updateCount);
            result.put("message", "已按 revoke_commission 风格完成更新");

            ResponseObject responseObject = ResponseObject.newOkResponse();
            responseObject.setData(result);
            return responseObject;

        } catch (SQLException e) {
            // 异常回滚（不变）
            if (connUpdate != null && !connUpdate.isClosed()) {
                try {
                    connUpdate.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            e.printStackTrace();
            return ResponseObject.newErrResponse("处理失败：" + e.getMessage());
        } finally {
            // 关闭连接（不变）
            if (connUpdate != null && !connUpdate.isClosed()) {
                DBSql.close(connUpdate);
            }
        }
    }


}

