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

import com.actionsoft.bpms.bo.design.cache.BOCache;
import com.actionsoft.bpms.bo.design.model.BOItemModel;
import com.actionsoft.bpms.bo.design.model.BOModel;
import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
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.service.contractService;
import com.awspaas.user.apps.donenow_ctt.service.contractServiceAdj;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

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

/**
 * 合同创建时，使用的接口
 */
@Controller
public class contractCreateController {
    private static final Logger contractLogger = SDK.getLogAPI().getLogger(contractCreateController.class);//记录日志

    /**
     * 提交合同
     * @param uc
     * @param bindid
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_submit")
    public ResponseObject contractSubmit(UserContext uc, String bindid) {

        contractLogger.info("contractLogger.info 合同提交后---------------" + bindid);

        Map<String, Object> result = contractService.getInstance().SaveContract(uc, bindid, true);//保存合同


        if (result.getOrDefault("success", false).equals(true)) {


        } else {
            return ResponseObject.newErrResponse("保存失败！");
        }


        return ResponseObject.newOkResponse("保存成功！");
    }

    /**
     * 获取合同详情
     * @param uc
     * @param bindid
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.get_contractapply")
    public ResponseObject getContractApply(UserContext uc, String bindid) {

        RowMap contractDetail = DBSql.getMap("SELECT ID,BINDID,PROCESSDEFID FROM BO_EU_DNCTT_CONTRACT WHERE BINDID=? ", new Object[]{bindid});
        if (contractDetail == null || contractDetail.isEmpty())
            contractDetail = DBSql.getMap("SELECT ID,BINDID,PROCESSDEFID FROM BO_EU_DNCTT_CONTRACT_APPLY WHERE BINDID=? ", new Object[]{bindid});

        ResponseObject responseObject = ResponseObject.newOkResponse();

        responseObject.setData(contractDetail);

        return responseObject;
    }

    /**
     * 删除合同
     * @param uc
     * @param bindid
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_delete")
    public ResponseObject contractDelete(UserContext uc, String bindid, String id) throws SQLException {

        StringBuilder errorMsg = new StringBuilder();

// 1. 查询“项目”关联数
        String projectSql = "SELECT COUNT(0) FROM BO_EU_DNPRO_PROJECT WHERE CONTRACT_ID=? AND CLOSED=0";
        String projectCountStr = DBSql.getString(projectSql, new Object[]{id});
        int projectCount = StringUtils.isBlank(projectCountStr) ? 0 : Integer.parseInt(projectCountStr);
        if (projectCount > 0) {
            errorMsg.append(projectCount).append("个项目");
        }

// 2. 查询“工单/任务”关联数
        String taskSql = "SELECT COUNT(0) FROM BO_EU_DNSDK_TASK WHERE CONTRACT_ID=?";
        String taskCountStr = DBSql.getString(taskSql, new Object[]{id});
        int taskCount = StringUtils.isBlank(taskCountStr) ? 0 : Integer.parseInt(taskCountStr);
        if (taskCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(taskCount).append("个工单/任务");
        }

// 3. 查询“配置项”关联数
        String productSql = "SELECT COUNT(0) FROM BO_EU_DNCRM_INSTALLED_PRODUCT WHERE CONTRACT_ID=? AND CLOSED=0";
        String productCountStr = DBSql.getString(productSql, new Object[]{id});
        int productCount = StringUtils.isBlank(productCountStr) ? 0 : Integer.parseInt(productCountStr);
        if (productCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(productCount).append("个配置项");
        }

// 4. 查询“合同产品”关联数
        String contractCostSql = "SELECT COUNT(0) FROM BO_EU_DNCTT_CONTRACT_COST WHERE CONTRACT_ID=? AND CLOSED=0";
        String contractCostCountStr = DBSql.getString(contractCostSql, new Object[]{id});
        int contractCostCount = StringUtils.isBlank(contractCostCountStr) ? 0 : Integer.parseInt(contractCostCountStr);
        if (contractCostCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(contractCostCount).append("个合同产品");
        }

// 5. 查询“已计费条目”关联数
        String deductionSql = "SELECT COUNT(0) FROM BO_EU_DNCRM_ACCOUNT_DEDUCTION WHERE CONTRACT_ID=?";
        String deductionCountStr = DBSql.getString(deductionSql, new Object[]{id});
        int deductionCount = StringUtils.isBlank(deductionCountStr) ? 0 : Integer.parseInt(deductionCountStr);
        if (deductionCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(deductionCount).append("个已计费条目");
        }

// 6. 查询“工时”关联数
        String workEntrySql = "SELECT COUNT(0) FROM BO_EU_DNSDK_WORK_ENTRY WHERE CONTRACT_ID=?";
        String workEntryCountStr = DBSql.getString(workEntrySql, new Object[]{id});
        int workEntryCount = StringUtils.isBlank(workEntryCountStr) ? 0 : Integer.parseInt(workEntryCountStr);
        if (workEntryCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(workEntryCount).append("个工时");
        }

        String contractServiceSql = "SELECT COUNT(0) FROM BO_EU_DNCTT_CONTRACT_SERVICE WHERE CONTRACT_ID=? AND CLOSED=0";
        String contractServiceCountStr = DBSql.getString(contractServiceSql, new Object[]{id});
        int contractServiceCount = StringUtils.isBlank(contractServiceCountStr) ? 0 : Integer.parseInt(contractServiceCountStr);
        if (contractServiceCount > 0) {
            if (errorMsg.length() > 0) errorMsg.append("\n"); // 替换为纯文本换行符
            errorMsg.append(contractServiceCount).append("个合同服务");
        }

        if (errorMsg.length() > 0) {
            return ResponseObject.newErrResponse("该合同关联了:\n" + errorMsg.toString() + "，无法删除！");
            // 开头也添加\n，让第一个关联项也换行显示（可选，根据排版需求调整）
        }


        //如果服务已经审批并提交，则不能删除
        //合同初始费用审批
        int cnt = DBSql.getInt("SELECT COUNT(0) FROM BO_EU_DNCTT_CONTRACT WHERE (ID=? OR BINDID=?) AND SETUP_FEE!=0 AND SETUP_FEE IS NOT NULL AND CLOSED=0", new Object[]{id, bindid});
        if (cnt > 0) {
            return ResponseObject.newErrResponse("该合同合同初始费用已审批并提交，无法删除！");
        }

        cnt = DBSql.getInt("SELECT COUNT(0) FROM BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST WHERE (CONTRACT_ID=? OR BINDID=?) AND APPROVE_AND_POST_DATE IS NOT NULL ", new Object[]{id, bindid});
        if (cnt > 0) {
            return ResponseObject.newErrResponse("该合同服务已审批并提交，无法删除！");
        }

        cnt = DBSql.getInt("SELECT COUNT(0) FROM BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD WHERE (CONTRACT_ID=? OR BINDID=?) AND APPROVE_AND_POST_DATE IS NOT NULL ", new Object[]{id, bindid});
        if (cnt > 0) {
            return ResponseObject.newErrResponse("该合同服务已审批并提交，无法删除！");
        }


        Connection conn = null;
        try {
            conn = DBSql.open();
            conn.setAutoCommit(false);

            Map<String, Object> params = new HashMap<>();
            params.put("CONTRACT_ID", id);
            params.put("BINDID", bindid);
            //软删除
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_RATE", params, conn);
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_MILESTONE", params, conn);
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE", params, conn);
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_COST_DEFAULT", params, conn);

            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST", params, conn);
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_SALE_ADJUST", params, conn);
            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", params, conn);

            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_BUNDLE_SERVICE", " CONTRACT_SERVICE_ID IN (SELECT ID FROM BO_EU_DNCTT_CONTRACT_SERVICE WHERE (CONTRACT_ID=:CONTRACT_ID OR BINDID=:BINDID)) ", params, conn);

            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST_BUNDLE_SERVICE", " CONTRACT_SERVICE_ADJUST_ID IN (SELECT ID FROM BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST WHERE (CONTRACT_ID=:CONTRACT_ID OR BINDID=:BINDID))  ", params, conn);


            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST_BUNDLE_SERVICE", " CONTRACT_SERVICE_ADJUST_ID IN (SELECT ID FROM BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST WHERE (CONTRACT_ID=:CONTRACT_ID OR BINDID=:BINDID)) ", params, conn);

            updateContractCLOSED(uc, "BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD_BUNDLE_SERVICE", " CONTRACT_SERVICE_PERIOD_ID IN (SELECT ID FROM BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD WHERE (CONTRACT_ID=:CONTRACT_ID OR BINDID=:BINDID))  ", params, conn);

            BO contractBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT", id);
            if (contractBO != null) {
                contractBO.set("CLOSED", 1);
                dn.recordFormChanges.record(uc, contractBO, "删除合同");
                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", contractBO, conn);
            }
            if (contractBO == null || contractBO.getBindId().equals(bindid) == false) {
                contractBO = SDK.getBOAPI().getByProcess("BO_EU_DNCTT_CONTRACT", bindid);
                if (contractBO != null) {
                    contractBO.set("CLOSED", 1);
                    dn.recordFormChanges.record(uc, contractBO, "删除合同");
                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", contractBO, conn);
                }
            }

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


    /**
     * 关闭合同相关
     * @param uc
     * @param boName
     * @param params
     * @param conn
     */
    private void updateContractCLOSED(UserContext uc, String boName, String SqlWhere, Map<String, Object> params, Connection conn) {
        //获取需要删除的数据

        BOModel boModel = BOCache.getInstance().getModelByEntityName(boName);
        BOItemModel CLOSED = boModel.getItem("CLOSED");

        if (CLOSED != null && CLOSED.getName().equals("CLOSED")) {
            SqlWhere += " AND CLOSED=0";
        }

        List<BO> boList = SDK.getBOAPI().query(boName).addQuerySqlWhere(SqlWhere, params).list();
        for (BO bo : boList) {
            //记录删除日志
            dn.recordFormChanges.deleteBeforeRecord(uc, boName, bo.getId(), "删除", conn);
            SDK.getBOAPI().remove(boName, bo.getId(), conn);
        }
    }

    private void updateContractCLOSED(UserContext uc, String boName, Map<String, Object> params, Connection conn) {
        //获取需要删除的数据

        BOModel boModel = BOCache.getInstance().getModelByEntityName(boName);
        BOItemModel CLOSED = boModel.getItem("CLOSED");
        String whereSql = "";
        if (CLOSED != null && CLOSED.getName().equals("CLOSED")) {
            whereSql = " AND CLOSED=0";
        }

        List<BO> boList = SDK.getBOAPI().query(boName).addQuerySqlWhere(" (CONTRACT_ID=:CONTRACT_ID OR BINDID=:BINDID) " + whereSql, params).list();
        for (BO bo : boList) {
            //记录删除日志
            dn.recordFormChanges.deleteBeforeRecord(uc, boName, bo.getId(), "删除", conn);
            SDK.getBOAPI().remove(boName, bo.getId(), conn);
        }
    }


    /**
     * 合同产品删除
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_cost_delete", desc = "合同产品删除")
    public ResponseObject deleteContractProduct(UserContext uc, String costIds) {
        if (StringUtils.isBlank(costIds)) return ResponseObject.newErrResponse("请选择要删除的条目！");

        String[] costIdArr = costIds.split(",");
        String sql = "SELECT * FROM BO_EU_DNCTT_CONTRACT_COST WHERE ID IN(";
        for (int i = 0; costIdArr.length > i; i++) {
            sql += "?,";
        }
        sql = sql.substring(0, sql.length() - 1) + ")";
        List<RowMap> costList = DBSql.getMaps(sql, Arrays.stream(costIdArr).toArray());

        List<String> errorList = new ArrayList<>();
        for (RowMap cost : costList) {
            //1、判断是否拣货
            if (DBSql.getInt("SELECT COUNT(ID) FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT WHERE CONTRACT_COST_ID=?", new Object[]{cost.getString("ID")}) > 0) {
                errorList.add(cost.getString("NAME") + "已拣货");
            }
            //2、判断是否创建采购单
            if (DBSql.getInt("SELECT COUNT(ID) FROM BO_EU_DNIVT_ORDER_PRODUCT WHERE CONTRACT_COST_ID=?", new Object[]{cost.getString("ID")}) > 0) {
                errorList.add(cost.getString("NAME") + "已创建采购单");
            }
        }

        if (errorList.size() > 0) {
            return ResponseObject.newErrResponse(StringUtils.join(errorList, "、") + "，无法删除！");
        }

        for (RowMap cost : costList) {
            SDK.getProcessAPI().deleteById(cost.getString("BINDID"), uc.getUID());
        }
        return ResponseObject.newOkResponse();
    }

    /**
     * 删除合同服务
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_delete", desc = "删除合同服务")
    public ResponseObject deleteContractService(UserContext uc, String serviceIds) {
        String[] costIdArr = serviceIds.split(",");

        String selSql = "SELECT * FROM BO_EU_DNCTT_CONTRACT_SERVICE WHERE ID IN(";
        for (int i = 0; costIdArr.length > i; i++) {
            selSql += "?,";
        }
        selSql = selSql.substring(0, selSql.length() - 1) + ")";
        List<RowMap> serviceList = DBSql.getMaps(selSql, Arrays.stream(costIdArr).toArray());

        //已审批的合同服务不能删除
        for (RowMap service : serviceList) {
            if (DBSql.getInt("SELECT count(1) FROM BO_EU_DNCTT_CONTRACT_SERVICE_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 CONTRACT_ID=? and CONTRACT_SERVICE_ID=? ", new Object[]{service.get("CONTRACT_ID"), service.get("ID")}) > 0) {
                return ResponseObject.newErrResponse("已审批合同服务，无法删除！");
            }

            String CONTRACT_COST_ID = DBSql.getString("SELECT ID FROM BO_EU_DNCTT_CONTRACT_COST WHERE IS_SERVICE_PRODUCT=1 AND SERVICE_ID=?", new Object[]{service.get("ID")});

            if (StringUtils.isNotBlank(CONTRACT_COST_ID)) {
                //采购订单相关也有删除
                List<BO> costProducts = SDK.getBOAPI().query("BO_EU_DNCTT_CONTRACT_COST_PRODUCT").addQuery("CONTRACT_COST_ID =", CONTRACT_COST_ID).list();
                if (costProducts.size() > 0) return ResponseObject.newErrResponse("已经生成采购订单，请先删除采购订单");
            }
        }

        for (RowMap service : serviceList) {
            //删除关联的服务调整
            List<String> csaIdList = DBSql.getList("select ID from BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST where CONTRACT_ID=? and CONTRACT_SERVICE_ID=?", String.class, new Object[]{service.get("CONTRACT_ID"), service.get("ID")});

            for (String csaId : csaIdList) {
                DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST_BUNDLE_SERVICE where CONTRACT_SERVICE_ADJUST_ID=? ", new Object[]{csaId});
            }

            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_ADJUST where  CONTRACT_ID=? and CONTRACT_SERVICE_ID=?", new Object[]{service.get("CONTRACT_ID"), service.get("ID")});

            //删除关联的服务周期
            List<String> cspIdList = DBSql.getList("select ID from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD where  CONTRACT_ID=? and OBJECT_ID=? and CONTRACT_SERVICE_ID=?", String.class, new Object[]{service.get("CONTRACT_ID"), service.get("OBJECT_ID"), service.get("ID")});
            for (String cspId : cspIdList) {
                DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD_BUNDLE_SERVICE where CONTRACT_SERVICE_PERIOD_ID=? ", new Object[]{cspId});
            }
            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD where CONTRACT_ID=? and OBJECT_ID=? and CONTRACT_SERVICE_ID=?", new Object[]{service.get("CONTRACT_ID"), service.get("OBJECT_ID"), service.get("ID")});

            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE where  ID=?", new Object[]{service.get("ID")});

            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_EDIT where  CONTRACT_SERVICE_ID=?", new Object[]{service.get("ID")});

            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST where IS_SERVICE_PRODUCT=1 AND SERVICE_ID=?", new Object[]{service.get("ID")});

        }

        return ResponseObject.newOkResponse();
    }

    /**
     * 编辑合同服务
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_edit")
    public ResponseObject editContractService(UserContext uc, String serviceId) {

        RowMap contractService = DBSql.getMap("SELECT * FROM BO_EU_DNCTT_CONTRACT_SERVICE WHERE ID=?", new Object[]{serviceId});
        contractService.remove("ID");
        contractService.remove("BINDID");

        ProcessInstance contractInstance = SDK.getProcessAPI().createBOProcessInstance("obj_e4b0c7ae587c406b808f3a4785f05e23", uc.getUID(), "服务调整-" + contractService.getString("NAME") + "-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));

        BO editBO = new BO();

        contractService.remove("CREATEDATE");
        contractService.remove("CREATEUSER");

        editBO.setAll(contractService);
        editBO.set("CONTRACT_SERVICE_ID", serviceId);
        editBO.set("OLD_UNIT_PRICE", contractService.get("UNIT_PRICE"));
        editBO.set("OLD_TOTAL_PRICE", contractService.get("TOTAL_PRICE"));
        editBO.set("OLD_UNIT_COST", contractService.get("UNIT_COST"));
        editBO.set("OLD_QUANTITY", contractService.get("QUANTITY"));
        editBO.set("OLD_TOTAL_COST", contractService.get("TOTAL_COST"));
        editBO.setBindId(contractInstance.getId());

        String maxEffectiveDate = DBSql.getString("SELECT MAX(EFFECTIVE_DATE) FROM BO_EU_DNCTT_CONTRACT_SERVICE_EDIT WHERE CONTRACT_ID=? and CONTRACT_SERVICE_ID=? and IS_EFFECTIVE='已执行' ", new Object[]{contractService.get("CONTRACT_ID"), serviceId});
        if (StringUtils.isBlank(maxEffectiveDate))
            maxEffectiveDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        editBO.set("EFFECTIVE_DATE", maxEffectiveDate);
        editBO.set("IS_EFFECTIVE", "未执行");
        SDK.getBOAPI().create("BO_EU_DNCTT_CONTRACT_SERVICE_EDIT", editBO, contractInstance, uc);

        String processUrl = SDK.getFormAPI().getFormURL(SDK.getPortalAPI().getPortalUrl(), uc.getSessionId(), contractInstance.getId(), null, 1, null, editBO.getId(), null, true);

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

        return responseObject;
    }


    /**
     * 生成合同服务周期
     * @param uc
     * @param contractId
     * @param serviceIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_period")
    public ResponseObject servicePeriod(UserContext uc, String contractId, String serviceIds) {

        if (StringUtils.isBlank(contractId))
            return ResponseObject.newErrResponse("请选择合同");
        if (StringUtils.isBlank(serviceIds))
            return ResponseObject.newErrResponse("请选择合同服务");

        BO contractBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT", contractId);

        // 1、合同开始日期或结束日期变化
        LocalDate START_DATE = getLocalDate(contractBO.get("START_DATE"));//服务开始日期
        LocalDate END_DATE = getLocalDate(contractBO.get("END_DATE"));//合同结束日期

        if (END_DATE == null || START_DATE == null) {
            return ResponseObject.newErrResponse("请先设置合同计费开始日期和计费结束日期");
        }

        if (START_DATE.isAfter(END_DATE)) {
            return ResponseObject.newErrResponse("合同开始日期不能大于结束日期");
        }

        List<BO> services = new ArrayList<>();
        for (String serviceId : serviceIds.split(",")) {
            BO contraService = SDK.getBOAPI().query("BO_EU_DNCTT_CONTRACT_SERVICE").addQuery("CONTRACT_ID =", contractId).addQuery("ID =", serviceId).detail();

            LocalDate EFFECTIVE_DATE = getLocalDate(contraService.get("EFFECTIVE_DATE"));//服务生效日期
            if (EFFECTIVE_DATE == null) {
                return ResponseObject.newErrResponse("请先设置服务生效日期");
            }
            if (EFFECTIVE_DATE.isBefore(START_DATE) || EFFECTIVE_DATE.isAfter(END_DATE)) {
                return ResponseObject.newErrResponse("服务生效日期必须在合同计费开始日期和结束日期之间");
            }

            //如果已经做了服务调整，则不能重新生成服务周期， 跳过就行

            if (DBSql.getInt("SELECT COUNT(1) CNT FROM BO_EU_DNCTT_CONTRACT_SERVICE_SALE_ADJUST WHERE CONTRACT_SERVICE_ID=? ", new Object[]{serviceId}) > 0 && DBSql.getInt("SELECT COUNT(1) CNT FROM BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD WHERE CONTRACT_SERVICE_ID=? ", new Object[]{serviceId}) > 0) {
                continue;
            }

            services.add(contraService);
        }

        if (services.size() == 0) {
            return ResponseObject.newOkResponse();
        }

        StringBuilder errMsg = new StringBuilder();
        StringBuilder succMsg = new StringBuilder();
        Connection conn = null;
        try {
            conn = DBSql.open();
            conn.setAutoCommit(false);

            RowMap dto = new RowMap(contractBO.asMap());
            for (BO contraService : services) {
                //2、服务调整:生效日期在合同开始日期和合同结束日期之间；已审批服务周期之后的日期；
                // 3、服务周期分为调整前和调整后两个周期；生效日期之后按照新的数量、单价重新生成服务周期；
                contractService.getInstance().AddService(uc, conn, dto, contraService);//保存合同
                contractService.getInstance().AddContractServiceProductOne(uc, dto, contraService, conn);//新增服务或者服务包--关联产品
                if (DBSql.getInt(conn, "SELECT count(1) FROM BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD WHERE CONTRACT_SERVICE_ID=? ", new Object[]{contraService.get("ID")}) == 0) {
                    errMsg.append(contraService.get("NAME") + "生成服务周期失败，");
                } else {
                    succMsg.append(contraService.get("NAME") + "生成服务周期成功，");
                }
            }

            conn.commit();
        } catch (SQLException e) {

            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            if (conn != null) DBSql.close(conn);
        }
        if (errMsg.length() > 0) {
            if (succMsg.length() > 0)
                return ResponseObject.newWarnResponse(succMsg.toString() + errMsg.toString());
            return ResponseObject.newErrResponse(errMsg.toString());
        }

        //分摊成本
        for (BO contraService : services) {
            contractServiceAdj.getInstance().paySplitServiceMonth(uc, contraService.getString("ID"));
        }

        return ResponseObject.newOkResponse();
    }

    /***
     * 生成合同服务成本
     * @param uc
     * @param contractId
     * @param serviceIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_cost")
    public ResponseObject serviceCost(UserContext uc, String contractId, String serviceIds) {

        if (StringUtils.isBlank(contractId))
            return ResponseObject.newErrResponse("请选择合同");
        if (StringUtils.isBlank(serviceIds))
            return ResponseObject.newErrResponse("请选择合同服务");

        BO contractBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT", contractId);

        // 1、合同开始日期或结束日期变化
        /*
        LocalDate START_DATE = getLocalDate(contractBO.get("START_DATE"));//服务开始日期
        LocalDate END_DATE = getLocalDate(contractBO.get("END_DATE"));//合同结束日期

        if (END_DATE == null || START_DATE == null) {
            return ResponseObject.newErrResponse("请先设置合同计费开始日期和计费结束日期");
        }

        if (START_DATE.isAfter(END_DATE)) {
            return ResponseObject.newErrResponse("合同开始日期不能大于结束日期");
        }

         */

        List<BO> services = new ArrayList<>();
        for (String serviceId : serviceIds.split(",")) {
            BO contraService = SDK.getBOAPI().query("BO_EU_DNCTT_CONTRACT_SERVICE").addQuery("CONTRACT_ID =", contractId).addQuery("ID =", serviceId).detail();

            /*

            LocalDate EFFECTIVE_DATE = getLocalDate(contraService.get("PURCHASE_START_DATE"));//服务生效日期
            if (EFFECTIVE_DATE == null) {
                return ResponseObject.newErrResponse("请先设置采购单开始日期");
            }
            if (EFFECTIVE_DATE.isBefore(START_DATE) || EFFECTIVE_DATE.isAfter(END_DATE)) {
                return ResponseObject.newErrResponse("采购单开始日期必须在合同计费开始日期和结束日期之间");
            }

            */

            String NEED_PURCHASE = contraService.getString("NEED_PURCHASE");
            if (NEED_PURCHASE.equals("1") == false) {
                return ResponseObject.newErrResponse("请选择需要采购的服务");
            }
            services.add(contraService);
        }

        StringBuilder errMsg = new StringBuilder();
        StringBuilder succMsg = new StringBuilder();

        Connection conn = null;
        try {
            conn = DBSql.open();
            conn.setAutoCommit(false);

            RowMap dto = new RowMap(contractBO.asMap());
            for (BO contraService : services) {

                contractService.getInstance().AddContractServiceProductOne(uc, dto, contraService, conn);//新增服务或者服务包--关联产品

                String contractCostId = DBSql.getString(conn, "select ID from BO_EU_DNCTT_CONTRACT_COST where IS_SERVICE_PRODUCT=1 AND  CONTRACT_ID=? and SERVICE_ID=? ", new Object[]{contraService.getString("CONTRACT_ID"), contraService.getString("ID")});

                if (StringUtils.isBlank(contractCostId)) {
                    errMsg.append(contraService.get("NAME") + "生成服务产品失败，");
                } else {
                    succMsg.append(contraService.get("NAME") + "生成服务产品成功，");
                }
            }

            conn.commit();
        } catch (SQLException e) {

            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            if (conn != null) DBSql.close(conn);
        }
        if (errMsg.length() > 0) {
            if (succMsg.length() > 0) return ResponseObject.newWarnResponse(succMsg.toString() + errMsg.toString());
            return ResponseObject.newErrResponse(errMsg.toString());
        }
        return ResponseObject.newOkResponse();
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_add")
    public ResponseObject serviceAdd(UserContext uc, String contractId) {
        ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_58693e03feac4879901430440b42efd9", uc.getUID(), "合同服务");
        BO service = new BO();
        service.setBindId(processInstance.getId());
        service.set("CONTRACT_ID", contractId);
        SDK.getBOAPI().create("BO_EU_DNCTT_CONTRACT_SERVICE", service, processInstance, uc);
        return ResponseObject.newOkResponse();
    }


    /**
     * 批量生产合同服务周期
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.contract_service_exec", session = false, noSessionEvaluate = "无安全隐患", noSessionReason = "批量生产")
    public String contractServicExec() {
        List<RowMap> services = DBSql.getMaps("SELECT CONTRACT_ID,GROUP_CONCAT(ID) IDS FROM bo_eu_dnctt_contract_service WHERE CONTRACT_ID in (SELECT ID FROM BO_EU_DNCTT_CONTRACT WHERE FRAMEWORK='7c2841c3-8f51-4dea-a6ea-984d9b9c3574' AND NO NOT LIKE '%old%' ) GROUP BY CONTRACT_ID");
        UserContext uc = UserContext.fromUID("admin");
        for (RowMap service : services) {
            String contractId = service.getString("CONTRACT_ID");
            String serviceIds = service.getString("IDS");
            servicePeriod(uc, contractId, serviceIds);
            serviceCost(uc, contractId, serviceIds);
        }
        return "ok";
    }

}
