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

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.TaskInstance;
import com.actionsoft.bpms.commons.database.RowMap;
import com.actionsoft.bpms.commons.htmlframework.HtmlPageTemplate;
import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
import com.actionsoft.bpms.org.cache.UserCache;
import com.actionsoft.bpms.org.model.UserModel;
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.bpms.util.TypeUtil;
import com.actionsoft.sdk.local.SDK;
import com.actionsoft.sdk.local.api.Logger;
import com.actionsoft.sdk.local.api.TaskAPI;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.awspaas.user.apps.donenow_ivt.cache.formStatusCache;
import com.awspaas.user.apps.donenow_ivt.constant.IVTConstant;
import com.awspaas.user.apps.donenow_ivt.service.PaymentPlanService;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.awspaas.user.apps.donenow_ivt.service.PaymentPlanService.toBigDecimal;

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

    /**
     * 添加供应商产品
     * @param uc
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.addVendorProduct")
    public ResponseObject addVendorProduct(UserContext uc, String vendorAccountId, String bindId, String processDefId, String warehouseProductIds, int type) {

        String sql = "select * from bo_eu_dnivt_product where id in(select product_id from bo_eu_dnivt_product_vendor where vendor_account_id=?";

        if (type == 1) //加载供应商默认产品
        {
            sql += " and is_default=1 ";
        } else if (type == 2)//加载供应商全部产品
        {

        }
        sql += " ) and CLOSED=0";
        List<RowMap> list = DBSql.getMaps(sql, new Object[]{vendorAccountId});
        if (list.isEmpty()) return ResponseObject.newErrResponse("无数据");

        List<JSONObject> warehouseProductIdsMap = new ArrayList<>();
        if (warehouseProductIds != null && !warehouseProductIds.isEmpty() && !warehouseProductIds.equals("[]")) {
            JSONArray warehouseProductIdsArray = JSONArray.parseArray(warehouseProductIds);
            for (int i = 0; i < warehouseProductIdsArray.size(); ++i) {
                warehouseProductIdsMap.add(warehouseProductIdsArray.getJSONObject(i));
            }
        }

        int cnt = 0;
        for (RowMap map : list) {
            List<RowMap> lctList = DBSql.getMaps("select id,warehouse_id,product_id,quantity,quantity_minimum,quantity_maximum,(select name from bo_eu_dnivt_warehouse where id=warehouse_id) as bin from bo_eu_dnivt_warehouse_product where product_id=? ", new Object[]{map.getString("ID")});
            if (lctList == null || lctList.isEmpty()) continue;
            boolean isExist = false;
            if (!warehouseProductIdsMap.isEmpty()) {
                for (int j = 0; j < warehouseProductIdsMap.size(); ++j) {
                    if (warehouseProductIdsMap.get(j).getString("PRODUCT_ID").equals(map.getString("ID")) && warehouseProductIdsMap.get(j).getString("WAREHOUSE_ID").equals(lctList.get(j).getString("WAREHOUSE_ID"))) {
                        isExist = true;
                    }
                }
            }

            if (isExist) continue;

            for (RowMap rowMap : lctList) {
                cnt++;
                BO bo = new BO();
                bo.setBindId(bindId);
                bo.setProcessDefId(processDefId);
                bo.set("PRODUCT_ID", map.getString("ID"));
                bo.set("NAME", map.getString("NAME"));
                bo.set("PRODUCT_NAME", map.getString("NAME"));
                bo.set("WAREHOUSE_ID", rowMap.getString("WAREHOUSE_ID"));
                bo.set("QUANTITY", rowMap.getInt("QUANTITY_MAXIMUM") - rowMap.getInt("QUANTITY"));
                bo.set("UNIT_COST", map.getString("UNIT_COST"));
                bo.set("WAS_AUTO_FILLED", 1);
                SDK.getBOAPI().createDataBO("BO_EU_DNIVT_ORDER_PRODUCT", bo, uc);
            }
        }
        if (cnt == 0) return ResponseObject.newErrResponse("无数据");

        return ResponseObject.newOkResponse();
    }


    /**
     * 获取产品信息
     * @param uc
     * @param productId
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.getProductInfo")
    public ResponseObject getProductInfo(UserContext uc, String productId) {

        String sql = "select * from bo_eu_dnivt_product where id=?";

        RowMap map = DBSql.getMap(sql, new Object[]{productId});
        if (map == null) return ResponseObject.newErrResponse("无数据");

        Map<String, Object> result = new HashMap<>();
        result.put("NAME", map.getString("NAME"));
        result.put("UNIT_COST", map.getString("UNIT_COST"));
        result.put("UNIT_PRICE", map.getString("UNIT_PRICE"));

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

        return responseObject;
    }

    /**
     * 获取税种信息
     * @param uc
     * @param taxId
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.getTaxInfo")
    public ResponseObject getTaxInfo(UserContext uc, String taxId) {

        String sql = "select OID,NAME,EXT1 from bo_eu_dnd_general where is_active=1 and closed=0  and general_table_id=44 and orgid=? and oid=?";

        RowMap map = DBSql.getMap(sql, new Object[]{uc.getCompanyModel().getId(), taxId});
        if (map == null) return ResponseObject.newErrResponse("无数据");

        Map<String, Object> result = new HashMap<>();
        result.put("taxId", map.getString("OID"));
        result.put("NAME", map.getString("NAME"));
        result.put("TAX_RATE", map.getString("EXT1"));

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

        return responseObject;
    }


    /**
     * 配送
     * @param uc
     * @param costPdtIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.purchaseShip")
    public ResponseObject purchaseShip(UserContext uc, String costPdtIds) throws SQLException {
        if (StringUtils.isBlank(costPdtIds)) return ResponseObject.newErrResponse("无数据");

        List<RowMap> pdtList = DBSql.getMaps("select ID,STATUS_ID from bo_eu_dnctt_contract_cost_product where id in(?)", new Object[]{costPdtIds});
        if (pdtList.isEmpty()) return ResponseObject.newErrResponse("无数据");
        for (RowMap pdtMap : pdtList) {
            if (pdtMap.getString("STATUS_ID").equals("2158") == false)//待配送
            {
                return ResponseObject.newErrResponse("该订单状态不是待配送");
            }
        }

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

            for (RowMap pdtMap : pdtList) {
                pdtMap.put("STATUS_ID", "2159");//已配送
                BO pdtBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", pdtMap.getString("ID"));
                pdtBO.set("SHIPPING_TIME", new Date());//配送时间
                pdtBO.set("STATUS_ID", "2159");
                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", pdtBO, conn);

                pdtMap.putAll(pdtBO.asMap());
                String PRODUCT_ID = DBSql.getString("select PRODUCT_ID from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{pdtBO.getString("CONTRACT_COST_ID")});
                pdtMap.put("PRODUCT_ID", PRODUCT_ID);


                BO costBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST", pdtMap.getString("CONTRACT_COST_ID"));
                if (DBSql.getInt("select count(1) from bo_eu_dnctt_contract_cost_product where contract_cost_id=? and status_id<>2159", new Object[]{pdtMap.getString("CONTRACT_COST_ID")}) == 0) {
                    // 产品全部已配送，修改成本状态
                    costBO.set("STATUS_ID", "1237");// 已配送

                    //需要更新上面的成本UNIT_COST  ESTIMATED_COST ：产品来源于采购---从采购单获取，成本取自采购单；库存拣货，成本取自库存产品


                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST", costBO, conn);
                }

                ProcessInstance processInstance = SDK.getProcessAPI().createBOProcessInstance("obj_e15a8fedeaeb43dc85aa258a7e1cffcf", uc.getUID(), "产品配送转移库存");
                BO transfer = new BO();
                transfer.setBindId(processInstance.getId());
                transfer.set("PRODUCT_ID", costBO.getString("PRODUCT_ID"));
                transfer.set("TYPE_ID", "1482");  // 转移给客户
                transfer.set("QUANTITY", pdtMap.getInt("QUANTITY"));
                transfer.set("FROM_WAREHOUSE_ID", pdtMap.getString("WAREHOUSE_ID"));
                if (StringUtils.isNotBlank(costBO.getString("CONTRACT_ID"))) {
                    transfer.set("TO_ACCOUNT_ID", DBSql.getString("select account_id from bo_eu_dnctt_contract where id=?", new Object[]{costBO.getString("CONTRACT_ID")}));
                }
                transfer.set("TO_CONTRACT_ID", costBO.getString("CONTRACT_ID"));
                SDK.getBOAPI().create("BO_EU_DNIVT_TRANSFER", transfer, processInstance, uc, conn);

                // 保存库存数修改
                BO lctPdtBO = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT").addQuery("PRODUCT_ID=", costBO.getString("PRODUCT_ID")).addQuery("WAREHOUSE_ID=", pdtMap.getString("WAREHOUSE_ID")).detail();

                if (lctPdtBO != null) {
                    lctPdtBO.set("QUANTITY", lctPdtBO.get("QUANTITY", Integer.class) - pdtMap.getInt("QUANTITY"));
                    SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT", lctPdtBO, conn);

                    //序列号更新
                    List<String> sns = DBSql.getList("select sn from bo_eu_dnctt_contract_cost_product_sn where contract_cost_product_id=?", String.class, new Object[]{pdtMap.getString("ID")});
                    if (sns != null && !sns.isEmpty()) {
                        for (String sn : sns) {
                            BO lctPdtSnBO = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT_SN").addQuery("sn=", sn).addQuery("warehouse_product_id=", lctPdtBO.getId()).detail();
                            if (lctPdtSnBO != null) {
                                SDK.getBOAPI().remove("BO_EU_DNIVT_WAREHOUSE_PRODUCT_SN", lctPdtSnBO.getId(), conn);
                            }
                            BO tsfSnBO = new BO();
                            tsfSnBO.setBindId(processInstance.getId());
                            tsfSnBO.set("SN", sn);
                            tsfSnBO.set("TRANSFER_ID", transfer.getId());

                            SDK.getBOAPI().create("BO_EU_DNIVT_TRANSFER_SN", tsfSnBO, processInstance, uc, conn);
                        }
                    }

                }
            }

            //发送通知

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

    /**
     * 取消配送
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.purchaseUnShip")
    public ResponseObject purchaseUnShip(UserContext uc, String costPdtIds) throws SQLException {
        if (StringUtils.isBlank(costPdtIds)) return ResponseObject.newErrResponse("无数据");

        List<RowMap> pdtList = DBSql.getMaps("select ID,STATUS_ID,CONTRACT_COST_ID,QUANTITY,WAREHOUSE_ID,SN,SHIPPING_CONTRACT_COST_ID from bo_eu_dnctt_contract_cost_product where FIND_IN_SET(ID,?)", new Object[]{costPdtIds});

        if (pdtList.isEmpty()) return ResponseObject.newErrResponse("无数据");

        Connection conn = null;
        try {
            conn = DBSql.open();
            conn.setAutoCommit(false);
            for (RowMap pdtMap : pdtList) {
                BO pdtBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", pdtMap.getString("ID"));

                String PRODUCT_ID = DBSql.getString("select PRODUCT_ID from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{pdtBO.getString("CONTRACT_COST_ID")});
                pdtBO.set("STATUS_ID", "2158");//待配送
                pdtBO.set("SHIPPING_TIME", null);
                pdtBO.set("IS_SHIP", 0);
                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", pdtBO, conn);

                //修改成本状态
                BO costBO = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_COST", pdtBO.getString("CONTRACT_COST_ID"));

                if (costBO.getString("STATUS_ID").equals("1237")) {
                    // 修改成本状态
                    costBO.set("STATUS_ID", "1236");// 待配送
                    SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_COST", costBO, conn);
                }

                ProcessInstance processInstance = SDK.getProcessAPI().createBOProcessInstance("obj_e15a8fedeaeb43dc85aa258a7e1cffcf", uc.getUID(), "取消配送新建库存转移");
                BO tsf = new BO();
                tsf.setBindId(processInstance.getId());
                tsf.set("PRODUCT_ID", PRODUCT_ID);
                tsf.set("TYPE_ID", "1482");
                tsf.set("QUANTITY", pdtBO.get("QUANTITY"));
                tsf.set("FROM_WAREHOUSE_ID", pdtBO.getString("WAREHOUSE_ID"));
                if (StringUtils.isNotBlank(costBO.getString("CONTRACT_ID"))) {
                    tsf.set("TO_ACCOUNT_ID", DBSql.getString("select account_id from bo_eu_dnctt_contract where id=?", new Object[]{costBO.getString("CONTRACT_ID")}));
                }
                tsf.set("TO_CONTRACT_ID", costBO.getString("CONTRACT_ID"));

                tsf.set("SN", pdtMap.getString("SN"));
                SDK.getBOAPI().create("BO_EU_DNIVT_TRANSFER", tsf, processInstance, uc, conn);

                // 删除库存数修改
                BO lctPdtBO = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT").addQuery("PRODUCT_ID=", PRODUCT_ID).addQuery("WAREHOUSE_ID=", pdtBO.getString("WAREHOUSE_ID")).detail();

                if (lctPdtBO != null) {

                    //序列号更新
                    String sns = pdtMap.getString("SN");
                    if (sns != null && !sns.isEmpty()) {
                        //如何回到对应的批次上

                        for (String sn : sns.split(",")) {
                            BO lctPdtLotBO = SDK.getBOAPI().query("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT").addQuery("BINDID=", lctPdtBO.getBindId()).addQuery("FIND_IN_SET(" + sn + ",SHIPPED_SN)", null).detail();
                            lctPdtLotBO.set("QUANTITY", Integer.parseInt(lctPdtLotBO.getString("QUANTITY")) + 1);

                            String lostSN = lctPdtLotBO.getString("SN");
                            if (StringUtils.isNotBlank(lostSN)) lctPdtLotBO.set("SN", lostSN + "," + sn);
                            else lctPdtLotBO.set("SN", sn);

                            String lostShippedSN = lctPdtLotBO.getString("SHIPPED_SN");//移除sn

                            String[] lostShippedSNs = lostShippedSN.split(",");
                            List<String> lostShippedSNsList = new ArrayList<String>();
                            for (String lostShippedSNsItem : lostShippedSNs) {
                                if (!lostShippedSNsItem.equals(sn)) lostShippedSNsList.add(lostShippedSNsItem);
                            }
                            lostShippedSN = StringUtils.join(lostShippedSNsList.toArray(), ",");
                            lctPdtLotBO.set("SHIPPED_SN", lostShippedSN);
                            SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT_LOT", lctPdtLotBO, conn);
                        }

                        String wpsn = lctPdtBO.getString("SN");
                        if (StringUtils.isNotBlank(wpsn)) {
                            lctPdtBO.set("SN", wpsn + "," + sns);
                        } else {
                            lctPdtBO.set("SN", sns);
                        }
                    }

                    lctPdtBO.set("QUANTITY", lctPdtBO.get("QUANTITY", Integer.class) + pdtBO.get("QUANTITY", Integer.class));
                    SDK.getBOAPI().update("BO_EU_DNIVT_WAREHOUSE_PRODUCT", lctPdtBO, conn);
                }

                //删除
                if (StringUtils.isNotBlank(pdtMap.getString("SHIPPING_CONTRACT_COST_ID")))
                    DBSql.update(conn, "update BO_EU_DNCTT_CONTRACT_COST_PRODUCT set CLOSED=1 where ID=?", new Object[]{pdtMap.getString("SHIPPING_CONTRACT_COST_ID")});
                // DBSql.update(conn, "update BO_EU_DNCTT_CONTRACT_COST_PRODUCT set SHIPPING_CONTRACT_COST_ID=NULL where ID=?", new Object[]{pdtMap.getString("ID")});
            }


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


        return ResponseObject.newOkResponse();
    }

    /**
     * 打印配货单
     * @param uc
     * @param costPdtIds
     * @return
     * @throws SQLException
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.printPackingList")
    public String printPackingList(UserContext uc, String costPdtIds) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uc.getUID());
        map.put("sid", uc.getSessionId());
        map.put("costPdtIds", costPdtIds);

        List<RowMap> accountList = DBSql.getMaps("select DISTINCT a.ACCOUNT_ID,c.NAME as ACCOUNT_NAME from  bo_eu_dnctt_contract_cost a join bo_eu_dnctt_contract_cost_product b on a.id=b.contract_cost_id JOIN bo_eu_dncrm_account c ON a.ACCOUNT_ID=c.ID where  FIND_IN_SET(b.id,?)", new Object[]{costPdtIds});
        map.put("accountList", JSON.toJSONString(accountList));

        return HtmlPageTemplate.merge("PrintPackingList.html", map);
    }

    /**
     * 打印拣货单
     * @param uc
     * @param costPdtIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.printPickingList")
    public String printPickingList(UserContext uc, String costPdtIds) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uc.getUID());
        map.put("sid", uc.getSessionId());
        map.put("costPdtIds", costPdtIds);

        List<RowMap> accountList = DBSql.getMaps("select DISTINCT a.ACCOUNT_ID,c.NAME as ACCOUNT_NAME from  bo_eu_dnctt_contract_cost a join bo_eu_dnctt_contract_cost_product b on a.id=b.contract_cost_id JOIN bo_eu_dncrm_account c ON a.ACCOUNT_ID=c.ID where  FIND_IN_SET(b.id,?)", new Object[]{costPdtIds});
        map.put("accountList", JSON.toJSONString(accountList));

        return HtmlPageTemplate.merge("PrintPickingList.html", map);
    }

    /**
     * 获取成本产品列表
     * @param uc
     * @param costPdtIds
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.getCostProductPackList")
    public ResponseObject getCostProductPackList(UserContext uc, String costPdtIds, String accountId) {

        String sql = "SELECT T.ACCOUNT_NAME,( SELECT CONCAT( IFNULL(( SELECT CNNAME FROM BO_ACT_DICT_KV_ITEM WHERE ITEMNO = X.DISTRICT_ID AND DICTKEY = 'GB.ADDR'), '' ), IFNULL( X.ADDRESS, '' ), IFNULL( X.ADDITIONAL_ADDRESS, '' ), ' ', IFNULL( X.POSTAL_CODE, '' )) FROM BO_EU_DNCRM_LOCATION X WHERE X.ID = T.SHIP_TO ) AS SHIP_TO_ADDRESS, T.ACCOUNT_ID, T.SHIP_TO, GROUP_CONCAT( T.ID ) AS CONTRACT_COST_IDS FROM ( SELECT OP.ID, IFNULL( C.ACCOUNT_ID, IFNULL( P.ACCOUNT_ID, T.ACCOUNT_ID )) AS ACCOUNT_ID, ( SELECT NAME FROM CRM_ACCOUNT WHERE ID = IFNULL( C.ACCOUNT_ID, IFNULL( P.ACCOUNT_ID, T.ACCOUNT_ID ))) ACCOUNT_NAME, IFNULL(( SELECT LOCATION_ID FROM BO_EU_DNIVT_ORDER WHERE ID = OP.ORDER_ID ),( CASE WHEN SO.SHIP_TO_USE_ACCOUNT_ADDRESS = 1 OR SO.SHIP_TO_USE_BILL_TO_ADDRESS = 1 AND SO.BILL_TO_USE_ACCOUNT_ADDRESS = 1 THEN ( SELECT ID FROM CRM_LOCATION WHERE IS_DEFAULT = 1 AND ACCOUNT_ID = IFNULL( C.ACCOUNT_ID, IFNULL( P.ACCOUNT_ID, T.ACCOUNT_ID ))) WHEN SO.SHIP_TO_USE_BILL_TO_ADDRESS = 1 AND SO.BILL_TO_USE_ACCOUNT_ADDRESS = 0 THEN SO.BILL_TO_LOCATION_ID ELSE SO.SHIP_TO_LOCATION_ID END )) SHIP_TO FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT OP JOIN BO_EU_DNCTT_CONTRACT_COST B ON OP.CONTRACT_COST_ID = B.ID JOIN BO_EU_DNIVT_PRODUCT A ON B.PRODUCT_ID = A.ID LEFT JOIN BO_EU_DNCTT_CONTRACT C ON C.ID = B.CONTRACT_ID LEFT JOIN BO_EU_DNPRO_PROJECT P ON P.ID = B.PROJECT_ID LEFT JOIN BO_EU_DNSDK_TASK T ON T.ID = B.TASK_ID LEFT JOIN BO_EU_DNCRM_SALES_ORDER SO ON B.OPPORTUNITY_ID = SO.OPPORTUNITY_ID WHERE FIND_IN_SET(OP.ID,?) AND  (C.ACCOUNT_ID=? OR P.ACCOUNT_ID=? OR T.ACCOUNT_ID=?) ) T GROUP BY T.ACCOUNT_ID, T.SHIP_TO";

        //"ACCOUNT_NAME"	"SHIP_TO_ADDRESS"	"ACCOUNT_ID"	"SHIP_TO"	"CONTRACT_COST_IDS"
        List<RowMap> maps = DBSql.getMaps(sql, new Object[]{costPdtIds, accountId, accountId, accountId});
        for (RowMap map : maps) {
            //销售地址
            String SALES_ADDRESS = DBSql.getString("SELECT CONCAT( IFNULL(( SELECT CNNAME FROM BO_ACT_DICT_KV_ITEM WHERE ITEMNO = X.DISTRICT_ID AND DICTKEY = 'GB.ADDR'), '' ), IFNULL( X.ADDRESS, '' ), IFNULL( X.ADDITIONAL_ADDRESS, '' ), ' ', IFNULL( X.POSTAL_CODE, '' )) AS ADDRESS FROM BO_EU_DNCRM_LOCATION X WHERE X.ID =( SELECT B.LOCATION_ID FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT A JOIN BO_EU_DNIVT_ORDER B ON A.ORDER_ID = B.ID WHERE FIND_IN_SET(A.ID,?)  AND B.LOCATION_ID IS NOT NULL LIMIT 1 )", new Object[]{map.get("CONTRACT_COST_IDS")});
            map.put("SALES_ADDRESS", SALES_ADDRESS);

            List<RowMap> accountCosts = DBSql.getMaps("SELECT A.ID,A.CONTRACT_ID,A.PROJECT_ID,A.TASK_ID FROM  BO_EU_DNCTT_CONTRACT_COST  A JOIN BO_EU_DNCTT_CONTRACT_COST_PRODUCT B ON A.ID=B.CONTRACT_COST_ID WHERE FIND_IN_SET(B.ID,?) ", new Object[]{map.get("CONTRACT_COST_IDS")});

            String CONTRACT_INFO = null;
            String PROJECT_INFO = null;
            String TASK_INFO = null;
            //合同
            if (!accountCosts.isEmpty()) {
                List<String> contractIds = new ArrayList<>();
                List<String> projectIds = new ArrayList<>();
                List<String> taskIds = new ArrayList<>();
                for (RowMap accountCost : accountCosts) {
                    if (accountCost.get("CONTRACT_ID") != null && StringUtils.isNotBlank(accountCost.getString("CONTRACT_ID"))) {
                        contractIds.add(accountCost.getString("CONTRACT_ID"));
                    }
                    if (accountCost.get("PROJECT_ID") != null && StringUtils.isNotBlank(accountCost.getString("PROJECT_ID"))) {
                        projectIds.add(accountCost.getString("PROJECT_ID"));
                    }
                    if (accountCost.get("TASK_ID") != null && StringUtils.isNotBlank(accountCost.getString("TASK_ID"))) {
                        taskIds.add(accountCost.getString("TASK_ID"));
                    }
                }

                if (!contractIds.isEmpty()) {
                    CONTRACT_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNCTT_CONTRACT WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(contractIds, ",")});
                }
                if (!projectIds.isEmpty()) {
                    PROJECT_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNPRO_PROJECT WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(projectIds, ",")});
                }
                if (!taskIds.isEmpty()) {
                    TASK_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNSDK_TASK WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(taskIds, ",")});
                }
            }
            map.put("CONTRACT_INFO", CONTRACT_INFO);
            map.put("PROJECT_INFO", PROJECT_INFO);
            map.put("TASK_INFO", TASK_INFO);
            map.put("PACKINGS", DBSql.getMaps("SELECT DISTINCT A.CONTRACT_COST_ID AS CONTRACTCOSTID, A.QUANTITY,GROUP_CONCAT( A.SN ) AS SERIALNUMBER , C.`NAME` AS 'PRODUCTNAME' FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT A JOIN BO_EU_DNCTT_CONTRACT_COST B ON A.CONTRACT_COST_ID=B.ID JOIN BO_EU_DNIVT_PRODUCT C ON B.PRODUCT_ID=C.ID WHERE  FIND_IN_SET(A.ID,?) ", new Object[]{map.get("CONTRACT_COST_IDS")}));

        }
        ivtLogger.info(maps.toString());

        ResponseObject responseObject = ResponseObject.newOkResponse();
        responseObject.setData(maps);
        return responseObject;
    }

    /**
     * 拣货清单
     * @param uc
     * @param costPdtIds
     * @param accountId
     * @return
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.getCostProductPickList")
    public ResponseObject getCostProductPickList(UserContext uc, String costPdtIds, String accountId) {
        Map<String, Object> result = new HashMap<>();

        List<RowMap> costs = DBSql.getMaps("select a.* from  bo_eu_dnctt_contract_cost a join bo_eu_dnctt_contract_cost_product b on a.id=b.contract_cost_id JOIN bo_eu_dncrm_account c ON a.ACCOUNT_ID=c.ID where  FIND_IN_SET(b.id,?) AND a.ACCOUNT_ID=?", new Object[]{costPdtIds, accountId});

        List<RowMap> pickingProducts = DBSql.getMaps("SELECT DISTINCT C.ID AS 'CONTRACTCOSTID', A.QUANTITY, B.REFERENCE_NUMBER AS 'REFERENCENUMBER', B.BIN AS 'LOCATION', D.`NAME` AS 'WAREHOUSE', C.DESCRIPTION AS 'PRODUCTREMARK', P.`NAME` AS 'PRODUCTNAME' FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT A JOIN BO_EU_DNIVT_WAREHOUSE_PRODUCT B ON A.WAREHOUSE_ID = B.WAREHOUSE_ID JOIN BO_EU_DNCTT_CONTRACT_COST C ON C.PRODUCT_ID = B.PRODUCT_ID AND A.CONTRACT_COST_ID = C.ID JOIN BO_EU_DNIVT_WAREHOUSE D ON A.WAREHOUSE_ID = D.ID JOIN BO_EU_DNIVT_PRODUCT P ON P.ID = C.PRODUCT_ID WHERE FIND_IN_SET(A.ID,?) AND C.ACCOUNT_ID=? ", new Object[]{costPdtIds, accountId});

        String CONTRACT_INFO = null;
        String PROJECT_INFO = null;
        String TASK_INFO = null;
        //合同
        if (!costs.isEmpty()) {
            List<String> contractIds = new ArrayList<>();
            List<String> projectIds = new ArrayList<>();
            List<String> taskIds = new ArrayList<>();
            for (RowMap accountCost : costs) {
                if (accountCost.get("CONTRACT_ID") != null && StringUtils.isNotBlank(accountCost.getString("CONTRACT_ID"))) {
                    contractIds.add(accountCost.getString("CONTRACT_ID"));
                }
                if (accountCost.get("PROJECT_ID") != null && StringUtils.isNotBlank(accountCost.getString("PROJECT_ID"))) {
                    projectIds.add(accountCost.getString("PROJECT_ID"));
                }
                if (accountCost.get("TASK_ID") != null && StringUtils.isNotBlank(accountCost.getString("TASK_ID"))) {
                    taskIds.add(accountCost.getString("TASK_ID"));
                }
            }

            if (!contractIds.isEmpty()) {
                CONTRACT_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNCTT_CONTRACT WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(contractIds, ",")});
            }
            if (!projectIds.isEmpty()) {
                PROJECT_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNPRO_PROJECT WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(projectIds, ",")});
            }
            if (!taskIds.isEmpty()) {
                TASK_INFO = DBSql.getString("SELECT GROUP_CONCAT(`name`  SEPARATOR '<br/>'  ) FROM BO_EU_DNSDK_TASK WHERE FIND_IN_SET(ID,?) ", new Object[]{StringUtils.join(taskIds, ",")});
            }
        }
        result.put("CONTRACT_INFO", CONTRACT_INFO);
        result.put("PROJECT_INFO", PROJECT_INFO);
        result.put("TASK_INFO", TASK_INFO);
        result.put("PICKINGS", pickingProducts);


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

    }


    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.viewPurchaseOrder")
    public String viewPurchaseOrder(UserContext uc, String ID) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uc.getUID());
        map.put("sid", uc.getSessionId());
        RowMap purchaseOrder = DBSql.getMap("SELECT * FROM BO_EU_DNIVT_ORDER WHERE ID = ?", new Object[]{ID});
        List<RowMap> purchaseOrderProducts = DBSql.getMaps("SELECT * FROM bo_eu_dnivt_order_product WHERE ORDER_ID = ?", new Object[]{ID});

        map.put("purchase_order_no", purchaseOrder.getString("PURCHASE_ORDER_NO"));//采购订单号
        map.put("create_user_name", UserCache.getModel(purchaseOrder.getString("CREATEUSER")).getUserName());//创建人
        map.put("create_time", purchaseOrder.getString("CREATEDATE"));//创建时间
        map.put("external_purchase_order_no", purchaseOrder.getString("EXTERNAL_PURCHASE_ORDER_NO"));//外部采购订单号

        String vendor_name = StringUtils.EMPTY;
        String vendor_phone = StringUtils.EMPTY;
        if (StringUtils.isNotBlank(purchaseOrder.getString("VENDOR_ACCOUNT_ID"))) {
            UserModel vendorModel = UserCache.getModel(purchaseOrder.getString("VENDOR_ACCOUNT_ID"));
            if (vendorModel != null) {
                vendor_name = vendorModel.getUserName();
                vendor_phone = vendorModel.getMobile();
            }
        }
        map.put("vendor_name", vendor_name);
        map.put("vendor_phone", vendor_phone);//供应商


        String account_name = StringUtils.EMPTY;
        String account_phone = StringUtils.EMPTY;
        if (StringUtils.isNotBlank(purchaseOrder.getString("PURCHASE_ACCOUNT_ID"))) {
            UserModel accountModel = UserCache.getModel(purchaseOrder.getString("PURCHASE_ACCOUNT_ID"));
            if (accountModel != null) {
                account_name = accountModel.getUserName();
                account_phone = accountModel.getMobile();
            }
        }
        map.put("account_name", account_name);
        map.put("account_phone", account_phone);//供应商

        //合同
        map.put("contract", DBSql.getString("select GROUP_CONCAT(concat(name,' ',ifnull(description,'')) SEPARATOR '//') from bo_eu_dnctt_contract  where id in(select contract_id from bo_eu_dnctt_contract_cost where id in(select contract_cost_id from bo_eu_dnivt_order_product where closed=0 and order_id=?))", new Object[]{ID}));

        map.put("other_info", DBSql.getString("select concat( ifnull( (select concat('商机号:',GROUP_CONCAT(oid)) from bo_eu_dncrm_opportunity where id in(select opportunity_id from bo_eu_dnctt_contract_cost where id in(select contract_cost_id from bo_eu_dnivt_order_product where closed=0 and order_id=? )) ),''),' ', ifnull( (select concat('项目:',GROUP_CONCAT(name SEPARATOR '//')) from bo_eu_dnpro_project where id in(select project_id from bo_eu_dnctt_contract_cost where id in(select contract_cost_id from bo_eu_dnivt_order_product where closed=0 and order_id=? )) ),''), ' ', ifnull( (select concat('工单:',GROUP_CONCAT(no SEPARATOR '//') )from bo_eu_dnsdk_task where id in(select task_id from bo_eu_dnctt_contract_cost where id in(select contract_cost_id from bo_eu_dnivt_order_product where closed=0 and order_id=? )) ),'') )", new Object[]{ID, ID, ID}));

        map.put("order_phone", purchaseOrder.getString("PHONE"));

        map.put("payment_term", DBSql.getString("SELECT NAME FROM bo_eu_dnd_general WHERE OID = ? AND CLOSED=0 AND ORGID=?", new Object[]{purchaseOrder.getString("PAYMENT_TERM_ID"), uc.getCompanyModel().getId()}));//支付期限

        map.put("shipping_type", DBSql.getString("SELECT NAME FROM bo_eu_dnd_general WHERE OID = ? AND CLOSED=0 AND ORGID=?", new Object[]{purchaseOrder.getString("SHIPPING_TYPE_ID"), uc.getCompanyModel().getId()}));//配送类型

        map.put("expected_ship_date", purchaseOrder.getString("EXPECTED_SHIP_DATE"));

        map.put("note", purchaseOrder.getString("NOTE"));

        List<RowMap> taxCateList = DBSql.getMaps("SELECT * FROM bo_eu_dnd_general WHERE ORGID=? AND CLOSED=0 AND GENERAL_TABLE_ID=44", new Object[]{uc.getCompanyModel().getId()});

        double total_cost = 0.0D;
        List<Map<String, String>> items = new ArrayList<>();
        for (RowMap item : purchaseOrderProducts) {
            Map<String, String> itemMap = new HashMap<>();
            itemMap.put("name", item.getString("NAME"));
            itemMap.put("note", item.getString("NOTE"));
            double unit_cost = item.getDouble("UNIT_COST");
            total_cost += unit_cost;
            itemMap.put("unit_cost", String.format("%.2f", unit_cost));

            double tax_cost = 0.0D;
            String tax_category_id = item.getString("TAX_CATEGORY_ID");
            if (StringUtils.isNotBlank(tax_category_id)) {
                RowMap taxCat = taxCateList.stream().filter(taxCate -> taxCate.getString("ID").equals(tax_category_id)).findAny().orElse(null);
                if (taxCat != null) {
                    tax_cost = unit_cost * (taxCat.getDouble("EXT1") + 1);
                }
            }
            itemMap.put("tax_cost", String.format("%.2f", tax_cost));
            itemMap.put("quantity", item.getString("QUANTITY"));
            itemMap.put("total_cost", String.format("%.2f", unit_cost * item.getDouble("QUANTITY")));

            items.add(itemMap);
        }
        map.put("total_cost", total_cost);
        map.put("items", JSONObject.toJSONString(items));

        for (String key : map.keySet()) {
            map.putIfAbsent(key, StringUtils.EMPTY);
        }

        return HtmlPageTemplate.merge("ViewPurchaseOrder.html", map);
    }

    /**
     * 根据服务ID创建采购订单
     * @param uc
     * @param serviceIds
     * @return
     * @throws SQLException
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.createPurchaseOrderByServiceId")
    public ResponseObject createPurchaseOrderByServiceId(UserContext uc, String serviceIds) throws SQLException {
        String[] serviceArr = serviceIds.split(",");
        String sql = "SELECT ID,STATUS_ID FROM BO_EU_DNCTT_CONTRACT_COST WHERE SERVICE_ID IN(";
        for (int i = 0; i < serviceArr.length; i++) {
            sql += "?,";
        }
        sql = sql.substring(0, sql.length() - 1) + ")";
        List<RowMap> costList = DBSql.getMaps(sql, Arrays.stream(serviceArr).toArray());

        if (costList.isEmpty())
            return ResponseObject.newErrResponse("没有找到对应的合同产品");


        String costIds = costList.stream().map(cost -> cost.getString("ID")).collect(Collectors.joining(","));

        List<String> bindids = DBSql.getList("select BINDID from BO_EU_DNIVT_ORDER_PRODUCT where ISEND=0 AND FIND_IN_SET(CONTRACT_COST_ID,'" + costIds + "')>0", String.class);

        if (!bindids.isEmpty()) {
            for (String bindid : bindids) {
                if (!SDK.getProcessAPI().isEndById(bindid)) {

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

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

        return createPurchaseOrder(uc, costIds);
    }


    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.contract_serviceOrder_exec", session = false, noSessionEvaluate = "无安全隐患", noSessionReason = "批量生产")
    public String contractServicExec() throws SQLException {

        List<RowMap> services = DBSql.getMaps("SELECT CONTRACT_ID,ID 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%' ) AND `NAME` LIKE '%第三方施工费%' OR `NAME` LIKE '%一次性安装费%' ORDER BY CREATEDATE DESC");

        UserContext uc = UserContext.fromUID("admin");
        for (RowMap service : services) {

            String serviceIds = service.getString("ID");

            // String serviceIds = DBSql.getString("SELECT GROUP_CONCAT(ID) AS SERVICE_IDS FROM bo_eu_dnctt_contract_service WHERE NEED_PURCHASE=1 AND  AND FIND_IN_SET(CONTRACT_ID,?) AND UNIT_COST>0", new Object[]{service.getString("CONTRACT_IDS")});

            try {
                ResponseObject responseObject = createPurchaseOrderByServiceId(uc, serviceIds);


            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return "ok";
    }

    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.contract_serviceOrder_exec2", session = false, noSessionEvaluate = "无安全隐患", noSessionReason = "批量生产")
    public String contractServicExec2() throws SQLException {
        List<RowMap> services = DBSql.getMaps("SELECT DISTINCT c.ID FROM bo_eu_dnctt_contract_service a JOIN bo_eu_dnivt_order_product b ON a.ID=b.CONTRACT_SERVICE_ID JOIN wfc_task c ON b.BINDID=c.PROCESSINSTID WHERE  c.CONTROLSTATE='active' AND c.TASKSTATE=1  AND a.CONTRACT_ID in (SELECT ID FROM BO_EU_DNCTT_CONTRACT WHERE FRAMEWORK='7c2841c3-8f51-4dea-a6ea-984d9b9c3574' AND NO NOT LIKE '%old%' ) ");
        UserContext uc = UserContext.fromUID("admin");

        TaskAPI taskAPI = SDK.getTaskAPI();

        for (RowMap service : services) {
            String taskId = service.getString("ID");
            taskAPI.completeTask(taskId, "admin");
        }



        return "ok";
    }

    /**
     * 创建采购订单
     */
    @Mapping(value = "com.awspaas.user.apps.donenow_ivt.createPurchaseOrder")
    public ResponseObject createPurchaseOrder(UserContext uc, String costIds) throws SQLException {
        Connection conn = null;
        try {
            conn = DBSql.open();
            conn.setAutoCommit(false);
            ivtLogger.info("接收到的costIds参数: " + costIds);

// ========== 新增：初始化TAX_CATEGORY_ID与税率的映射关系 ==========
            /*
            Map<String, BigDecimal> taxRateMap = new HashMap<>();
            taxRateMap.put("597", new BigDecimal("0.00"));  // 增值税-0
            taxRateMap.put("598", new BigDecimal("0.01"));  // 增值税-1
            taxRateMap.put("599", new BigDecimal("0.03"));  // 增值税-3
            taxRateMap.put("10095", new BigDecimal("0.05")); // 增值税-5
            taxRateMap.put("10096", new BigDecimal("0.06")); // 增值税-6
            taxRateMap.put("10097", new BigDecimal("0.09")); // 增值税-9
            taxRateMap.put("14138", new BigDecimal("0.13")); // 增值税-13

             */
            List<RowMap> taxCateList = DBSql.getMaps("SELECT OID,NAME,ORGID,GENERAL_TABLE_ID,EXT1,CLOSED,IS_ACTIVE FROM BO_EU_DND_GENERAL WHERE  GENERAL_TABLE_ID=44 AND ORGID=? ", new Object[]{uc.getCompanyModel().getId()});
            Map<String, BigDecimal> taxRateMap = new HashMap<>();
            String zeroTaxTaxCateId = "";
            for (RowMap taxCate : taxCateList) {
                taxRateMap.put(taxCate.getString("OID"), toBigDecimal(taxCate.getDouble("EXT1")));
                if (toBigDecimal(taxCate.getDouble("EXT1")).compareTo(BigDecimal.ZERO) == 0) {
                    zeroTaxTaxCateId = taxCate.getString("OID");
                }
            }

            String[] costIdArr = costIds.split(",");
            String sql = "SELECT * FROM BO_EU_DNCTT_CONTRACT_COST WHERE ID IN(";
            for (int i = 0; i < costIdArr.length; i++) {
                sql += "?,";
            }
            sql = sql.substring(0, sql.length() - 1) + ")";
            List<RowMap> costList = DBSql.getMaps(sql, Arrays.stream(costIdArr).toArray());
            ivtLogger.info("查询到的合同成本数据条数: " + costList.size());

            BO purchaseOrder = new BO();
            purchaseOrder.set("SUBMIT_TIME", getCurrentDateTime());
            purchaseOrder.set("SUBMITTED_RESOURCE_ID", uc.getUID());

            Set<String> PURCHASE_ACCOUNT_ID = new HashSet<>();
            Set<String> VENDOR_ACCOUNT_ID = new HashSet<>();
            int validCount = 0;

            for (RowMap cost : costList) {
                // String account_id = cost.getString("ACCOUNT_ID");

                String account_id = cost.getString("BILL_ACCOUNT_ID");//计费客户
                String status_id = cost.getString("STATUS_ID");

                /*待采购/待拣货*/
                if (StringUtils.isNotBlank(status_id) && !"1234".equals(status_id)) {
                    continue;
                }

                List<String> bindids = DBSql.getList("select BINDID from BO_EU_DNIVT_ORDER_PRODUCT where ISEND=0 AND (CONTRACT_COST_ID=? or (CONTRACT_SERVICE_ID=? AND CONTRACT_SERVICE_ID IS NOT NULL AND CONTRACT_SERVICE_ID<>'')) ", String.class, new Object[]{cost.getString("ID"), cost.getString("SERVICE_ID")});
                if (!bindids.isEmpty()) {
                    for (String bindid : bindids) {
                        if (!SDK.getProcessAPI().isEndById(bindid)) {
                            // return ResponseObject.newErrResponse("有订单正在处理中，请勿重复提交");

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

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

                        }
                    }
                }

                if (StringUtils.isNotBlank(account_id)) {
                    PURCHASE_ACCOUNT_ID.add(account_id);
                } else {
                    account_id = DBSql.getString("select ACCOUNT_ID from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{cost.getString("CONTRACT_ID")});
                    if (StringUtils.isNotBlank(account_id)) {
                        DBSql.update("UPDATE BO_EU_DNCTT_CONTRACT_COST SET ACCOUNT_ID=? WHERE ID=?", new Object[]{account_id, cost.getString("ID")});
                        PURCHASE_ACCOUNT_ID.add(account_id);
                        cost.put("ACCOUNT_ID", account_id);
                    }
                }
                ivtLogger.info("处理的account_id: " + account_id);

                String PRODUCT_ID = cost.getString("PRODUCT_ID");
                String vendor_id = DBSql.getString("select VENDOR_ACCOUNT_ID from BO_EU_DNIVT_PRODUCT_VENDOR where PRODUCT_ID=? or BINDID in (select BINDID FROM BO_EU_DNIVT_PRODUCT WHERE ID=?)", new Object[]{PRODUCT_ID, PRODUCT_ID});
                if (StringUtils.isNotBlank(vendor_id)) {
                    VENDOR_ACCOUNT_ID.add(vendor_id);
                }

                ivtLogger.info("处理的vendor_id: " + vendor_id);

                int purchase_quantity = cost.getInt("QUANTITY") - DBSql.getInt("SELECT sum(a.QUANTITY) AS QU  FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT a  LEFT JOIN BO_EU_DNIVT_ORDER_PRODUCT b ON a.ORDER_ID=b.ORDER_ID AND a.CONTRACT_COST_ID=b.CONTRACT_COST_ID WHERE  ((a.ORDER_ID is NULL OR a.ORDER_ID='') OR b.ORDER_ID IS NOT NULL) AND  a.CONTRACT_COST_ID=?  and a.CLOSED=0", new Object[]{cost.getString("ID")});
                if (purchase_quantity <= 0) {
                    ivtLogger.info("采购数量<=0，跳过该记录，ID: " + cost.getString("ID"));
                    continue;
                }
                cost.put("PURCHASE_QUANTITY", purchase_quantity);
                validCount++;
            }


            if (validCount < 1) {
                ivtLogger.info("没有可处理的采购订单记录");
                return ResponseObject.newErrResponse("没有可处理的采购订单");
            }


            ProcessInstance processInstance;
            try {
                processInstance = SDK.getProcessAPI().createProcessInstance("obj_795cb3601f3a4b919b5896cf5b076a3a", uc.getUID(), "采购订单");
                ivtLogger.info("流程实例创建成功，ID: " + processInstance.getId());
            } catch (Exception e) {
                System.err.println("流程实例创建失败: " + e.getMessage());
                throw new RuntimeException("流程实例创建失败", e);
            }
            purchaseOrder.setBindId(processInstance.getId());

            if (PURCHASE_ACCOUNT_ID.size() == 1) {
                purchaseOrder.set("PURCHASE_ACCOUNT_ID", PURCHASE_ACCOUNT_ID.stream().findFirst().get());
            }
            if (VENDOR_ACCOUNT_ID.size() == 1) {
                purchaseOrder.set("VENDOR_ACCOUNT_ID", VENDOR_ACCOUNT_ID.stream().findFirst().get());
            }
            SDK.getBOAPI().createDataBO("BO_EU_DNIVT_ORDER", purchaseOrder, uc, conn);
            ivtLogger.info("采购单创建成功，ID: " + purchaseOrder.getId());

            for (RowMap cost : costList) {
                BO purchaseOrderProduct = new BO();
                purchaseOrderProduct.setBindId(processInstance.getId());
                String unitCostStr = cost.getString("UNIT_COST");

                int purchaseQuantity = cost.getInt("PURCHASE_QUANTITY");

                if (StringUtils.isBlank(unitCostStr) || purchaseQuantity <= 0) {
                    ivtLogger.info("无效计算参数：UNIT_COST=" + unitCostStr + "，+PURCHASE_QUANTITY=" + purchaseQuantity);
                    throw new RuntimeException("计算不含税金额失败：参数无效");
                }

                String taxCategoryId = null;
                //增值税发票，选择是时，才需要展示税率
                if(StringUtils.isNotBlank(cost.getString("IS_SERVICE_PRODUCT")) && "1".equals(cost.getString("IS_SERVICE_PRODUCT"))){
                    if (StringUtils.isNotBlank(cost.getString("SERVICE_ID"))) {
                        RowMap serviceMap = DBSql.getMap("select PURCHASE_TAX_CATEGORY_ID,VAT_TAX from BO_EU_DNCTT_CONTRACT_SERVICE where ID=?", new Object[]{cost.getString("SERVICE_ID")});
                        if (serviceMap.getString("VAT_TAX").equals("1")) {
                            taxCategoryId = serviceMap.getString("PURCHASE_TAX_CATEGORY_ID");
                        } else {
                            taxCategoryId = zeroTaxTaxCateId;
                        }
                    }
                }else {
                    taxCategoryId = cost.getString("TAX_CATEGORY_ID");
                }


                ivtLogger.info("taxCategoryId--- " + cost.getString("SERVICE_ID"));
                ivtLogger.info("taxCategoryId--- " + taxCategoryId);
                BigDecimal taxRate = taxRateMap.get(taxCategoryId);
                if (taxRate == null) {
                    System.err.println("未知TAX_CATEGORY_ID：" + taxCategoryId);
                    throw new RuntimeException("计算不含税金额失败：未知税率ID");
                }

                BigDecimal unitCost = new BigDecimal(unitCostStr);
                BigDecimal unitCostNotax = unitCost.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);

                BigDecimal costTotalNotax = unitCostNotax.multiply(new BigDecimal(purchaseQuantity)).setScale(2, RoundingMode.HALF_UP);
                purchaseOrderProduct.set("PURCHASE_ACCOUNT_ID", cost.getString("BILL_ACCOUNT_ID"));//使用计费客户
                purchaseOrderProduct.set("NAME", cost.getString("NAME"));
                purchaseOrderProduct.set("PRODUCT_ID", cost.getString("PRODUCT_ID"));
                purchaseOrderProduct.set("QUANTITY", cost.getString("PURCHASE_QUANTITY"));
                purchaseOrderProduct.set("UNIT_COST", cost.getString("UNIT_COST"));
                purchaseOrderProduct.set("TAX_CATEGORY_ID", taxCategoryId);

                String warehouseId = DBSql.getString("SELECT ID FROM bo_eu_dnivt_warehouse WHERE CATE_ID=2 AND ORGID=? ", new Object[]{uc.getCompanyModel().getId()});
                if (warehouseId == null) {
                    System.err.println("未查询到符合条件的仓库");
                    throw new RuntimeException("未查询到符合条件的仓库");
                }
                purchaseOrderProduct.set("WAREHOUSE_ID", warehouseId);
                purchaseOrderProduct.set("NOTE", cost.getString("DESCRIPTION"));
                purchaseOrderProduct.set("COST_TOTAL", cost.getString("EXTENDED_COST"));
                purchaseOrderProduct.set("CONTRACT_ID", cost.getString("CONTRACT_ID"));
                purchaseOrderProduct.set("PROJECT_ID", cost.getString("PROJECT_ID"));
                purchaseOrderProduct.set("TASK_ID", cost.getString("TASK_ID"));
                purchaseOrderProduct.set("CONTRACT_COST_ID", cost.getString("ID"));
                purchaseOrderProduct.set("CONTRACT_SERVICE_ID", cost.getString("SERVICE_ID"));
                purchaseOrderProduct.set("ORDER_ID", purchaseOrder.getId());
                purchaseOrderProduct.set("UNIT_COST_NOTAX", unitCostNotax);
                purchaseOrderProduct.set("COST_TOTAL_NOTAX", costTotalNotax);

                SDK.getBOAPI().createDataBO("BO_EU_DNIVT_ORDER_PRODUCT", purchaseOrderProduct, uc, conn);
                ivtLogger.info("采购项创建成功，关联采购单ID: " + purchaseOrder.getId());

                String PURCHASE_ORDER_NO = DBSql.getString("SELECT GROUP_CONCAT(PURCHASE_ORDER_NO) FROM " + IVTConstant.BO_EU_DNIVT_ORDER + " WHERE CLOSED=0 AND ID IN (SELECT ORDER_ID FROM BO_EU_DNIVT_ORDER_PRODUCT WHERE CONTRACT_COST_ID=?) ", new Object[]{cost.getString("ID")});
                DBSql.update(conn, "UPDATE BO_EU_DNCTT_CONTRACT_COST SET PURCHASE_ORDER_NO=? WHERE ID=?", new Object[]{PURCHASE_ORDER_NO, cost.getString("ID")});


                ProcessInstance costProductProcessInst = SDK.getProcessAPI().createBOProcessInstance("obj_6bc913271069455abbd516c556b26d31", uc.getUID(), "合同产品物流管理");

                //提交采购订单添加成本产品
                BO costProduct = new BO();
                costProduct.setBindId(costProductProcessInst.getId());
                costProduct.set("ORDER_ID", purchaseOrder.getId());
                costProduct.set("CONTRACT_COST_ID", cost.getString("ID"));
                costProduct.set("STATUS_ID", "2156");//采购中
                costProduct.set("QUANTITY", purchaseOrderProduct.get("QUANTITY"));
                costProduct.set("WAREHOUSE_ID", purchaseOrderProduct.get("WAREHOUSE_ID"));
                costProduct.set("OLD_QUANTITY", costProduct.get("QUANTITY"));//配送数量

                costProduct.set("SHIPPING_TYPE_ID", null);
                costProduct.set("COST_CODE_ID", cost.getString("COST_CODE_ID"));
                costProduct.set("COST_CODE_NAME", cost.getString("COST_CODE_NAME"));

                //服务产品
                if (StringUtils.isNotBlank(cost.getString("SERVICE_ID")) && cost.getString("IS_SERVICE_PRODUCT").equals("1"))
                    costProduct.set("IS_SERVICE_COST", 1);

                dn.recordFormChanges.record(uc, costProduct, "采购产品审批后新增");


                SDK.getBOAPI().create("BO_EU_DNCTT_CONTRACT_COST_PRODUCT", costProduct, costProductProcessInst, uc);

            }

            List<TaskInstance> taskInstances = SDK.getProcessAPI().start(processInstance).fetchActiveTasks();
            ivtLogger.info("流程启动成功，活动任务数: " + taskInstances.size());
            conn.commit();

            if (taskInstances.isEmpty()) {
                System.err.println("未查询到活动任务");
                throw new RuntimeException("未查询到活动任务");
            }
            TaskInstance taskInstance = taskInstances.get(0);

            String processUrl = SDK.getFormAPI().getFormURL(SDK.getPortalAPI().getPortalUrl(), uc.getSessionId(), processInstance.getId(), taskInstance.getId(), taskInstance.getState(), null, null, null, true);

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

            return responseObject;
        } catch (Exception e) {
            System.err.println("创建采购订单异常: " + e.getMessage());
            e.printStackTrace();
            if (conn != null) {
                try {
                    conn.rollback();    
                } catch (SQLException ex) {
                    System.err.println("事务回滚异常: " + ex.getMessage());
                }
            }
            return ResponseObject.newErrResponse("创建采购订单失败，原因: " + e.getMessage());
        } finally {
            DBSql.close(conn);
        }
    }

    private static String getCurrentDateTime() {
        String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
        return sdf.format(new Date());
    }

    /**
     * 修改采购订单状态
     * @param uc
     * @param orderId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.updateOrderStatus")
    public ResponseObject updateOrderStatus(UserContext uc, String orderId) {
        formStatusCache cache = formStatusCache.getInstance();
        cache.put(orderId, new Date());
        return ResponseObject.newOkResponse();
    }


    /**
     * 删除采购订单
     * @param uc
     * @param bindId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.deleteOrder")
    public ResponseObject deleteOrder(UserContext uc, String bindId) {
        BO order = SDK.getBOAPI().getByProcess("BO_EU_DNIVT_ORDER", bindId);

        List<BO> orderProducts = SDK.getBOAPI().query("BO_EU_DNIVT_ORDER_PRODUCT").addQuery("BINDID =", bindId).list();

        if (order.isEnd()) return ResponseObject.newErrResponse("采购订单已结束，不能删除");

        if (order.getString("ISEND").equals("1")) return ResponseObject.newErrResponse("采购订单已结束，不能删除");

        SDK.getProcessAPI().deleteById(bindId, uc.getUID());

        for (BO op : orderProducts) {
            String costProductID = DBSql.getString("SELECT ID FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT WHERE ORDER_ID=? AND CONTRACT_COST_ID=?", new Object[]{op.getString("ORDER_ID"), op.getString("CONTRACT_COST_ID")});

            if (StringUtils.isNotBlank(costProductID))
                DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST_PRODUCT where ID=?", new Object[]{costProductID});

            //如果是合同服务产生采购项
            if (DBSql.getString("select IS_SERVICE_PRODUCT from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{op.getString("CONTRACT_COST_ID")}).equals("1")) {
                DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{op.getString("CONTRACT_COST_ID")});
            }
        }

        SDK.getBOAPI().removeByBindId("BO_EU_DNIVT_ORDER", bindId);
        SDK.getBOAPI().removeByBindId("BO_EU_DNIVT_ORDER_PRODUCT", bindId);
        return ResponseObject.newOkResponse();
    }


    /**
     * 创建付款计划
     * @param uc
     * @param orderId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.ivt_createPaymentPlan")
    public ResponseObject createPaymentPlan(UserContext uc, String orderId) {

        //校验
        BO purchaseOrder = SDK.getBOAPI().get("BO_EU_DNIVT_ORDER", orderId);
        List<BO> orderProducts = SDK.getBOAPI().query("BO_EU_DNIVT_ORDER_PRODUCT").bindId(purchaseOrder.getBindId()).list();


        for (BO orderProduct : orderProducts) {
            if (StringUtils.isNotBlank(orderProduct.getString("CONTRACT_COST_ID"))) {
                String SERVICE_ID = DBSql.getString("select SERVICE_ID from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{orderProduct.getString("CONTRACT_COST_ID")});
                //关联服务
                if (StringUtils.isNotBlank(SERVICE_ID)) {

                    BO service = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE", SERVICE_ID);

                    String RULE_CATE = service.getString("PURCHASE_PERIOD_TYPE");//采购周期

                    //PERIOD_TYPE_ONCE = "609";       // 一次性收费
                    if (RULE_CATE.equals("609") == false) {

                        LocalDate PERIOD_BEGIN_DATE = service.get("PURCHASE_START_DATE", LocalDate.class);

                        /*
                        LocalDate START_DATE = TypeUtil.convert(DBSql.getString("select START_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);

                        LocalDate PERIOD_END_DATE = TypeUtil.convert(DBSql.getString("select END_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);

                         */
                        LocalDate START_DATE = PERIOD_BEGIN_DATE;
                        LocalDate PERIOD_END_DATE = service.get("PURCHASE_END_DATE", LocalDate.class);

                        //采购单开始日期
                        if (service.get("PURCHASE_START_DATE") != null) {
                            START_DATE = TypeUtil.convert(service.get("PURCHASE_START_DATE").toString().substring(0, 10), LocalDate.class);
                        }

                        String PURCHASE_CALC_METHOD_1STPERIOD = service.getString("PURCHASE_CALC_METHOD_1STPERIOD");

                        if (StringUtils.isBlank(RULE_CATE) || StringUtils.isBlank(PURCHASE_CALC_METHOD_1STPERIOD)) {
                            return ResponseObject.newErrResponse("采购周期规则或采购计划计算方式未设置");
                        }

                        if (PERIOD_BEGIN_DATE == null || PERIOD_END_DATE == null || START_DATE == null || PERIOD_BEGIN_DATE.isAfter(PERIOD_END_DATE) || START_DATE.isAfter(PERIOD_END_DATE)) {
                            return ResponseObject.newErrResponse("采购周期开始日期或结束日期未设置");
                        }


                        if (DBSql.getInt("select count(1) as cnt from  BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=?  AND PAY_AMOUNT is NOT null AND PAY_AMOUNT<>0", new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID}) > 0) {
                            return ResponseObject.newErrResponse("付款计划已经开始付款，不能重新生成");
                        }
                    }
                }
            }
        }

        PaymentPlanService.getInstance().createPaymentPlan(uc, orderId);

        //检查 是否创建成功
        if (DBSql.getInt("select count(1) CNT from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID=?", new Object[]{orderId}) == 0)
            return ResponseObject.newErrResponse("创建付款计划失败");

        return ResponseObject.newOkResponse();
    }


    /**
     * 检查付款计划是否修改
     * @param uc
     * @param requestBindidId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.checkPaymentPlans")
    public ResponseObject checkPaymentPlans(UserContext uc, String requestBindidId) {

        List<RowMap> list = DBSql.getMaps("select * from BO_EU_DNIVT_PAY_REQUEST_DETAIL where BINDID=?", new Object[]{requestBindidId});

        if (list.isEmpty()) return ResponseObject.newOkResponse();

        StringBuilder sb = new StringBuilder();
        for (RowMap detail : list) {
            String PAYMENT_PLAN_ID = detail.getString("PAYMENT_PLAN_ID");
            BigDecimal PLAN_AMOUNT = TypeUtil.convert(detail.get("PLAN_AMOUNT"), BigDecimal.class);

            RowMap plan = DBSql.getMap("select * from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ID=?", new Object[]{PAYMENT_PLAN_ID});

            BigDecimal PLAN_AMOUNT0 = TypeUtil.convert(plan.get("PLAN_AMOUNT"), BigDecimal.class);

            //比较是否相等
            if (isEqualUpToTwoDecimals(PLAN_AMOUNT, PLAN_AMOUNT0, RoundingMode.DOWN) == false) {
                ivtLogger.info("付款计划已修改:" + plan.getString("PAY_DESC") + ":" + PLAN_AMOUNT0 + ":" + PLAN_AMOUNT);
                sb.append(plan.getString("PAY_DESC")).append(":").append(PLAN_AMOUNT0).append(",");
            }
        }

        if (sb.length() > 0) {
            return ResponseObject.newOkResponse("付款计划已修改");
        }

        return ResponseObject.newOkResponse();
    }


    /**
     * 同步付款计划金额
     * @param uc
     * @param requestBindidId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.asnyPaymentPlans")
    public ResponseObject asnyPaymentPlans(UserContext uc, String requestBindidId) {

        List<RowMap> list = DBSql.getMaps("select * from BO_EU_DNIVT_PAY_REQUEST_DETAIL where BINDID=?", new Object[]{requestBindidId});

        if (list.isEmpty())
            return ResponseObject.newOkResponse();

        for (RowMap detail : list) {
            String PAYMENT_PLAN_ID = detail.getString("PAYMENT_PLAN_ID");
            BigDecimal PLAN_AMOUNT = TypeUtil.convert(detail.get("PLAN_AMOUNT"), BigDecimal.class);

            RowMap plan = DBSql.getMap("select * from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ID=?", new Object[]{PAYMENT_PLAN_ID});

            BigDecimal PLAN_AMOUNT0 = TypeUtil.convert(plan.get("PLAN_AMOUNT"), BigDecimal.class);


            //比较是否相等
            if (isEqualUpToTwoDecimals(PLAN_AMOUNT, PLAN_AMOUNT0, RoundingMode.DOWN) == false) {

                BO detailBO = SDK.getBOAPI().get("BO_EU_DNIVT_PAY_REQUEST_DETAIL", detail.getString("ID"));

                detailBO.set("PLAN_AMOUNT", PLAN_AMOUNT0);

                SDK.getBOAPI().update("BO_EU_DNIVT_PAY_REQUEST_DETAIL", detailBO);

            }
        }

        return ResponseObject.newOkResponse();
    }


    /**
     * 判断两个BigDecimal是否在小数点后两位及以上相等
     * @param a 第一个BigDecimal
     * @param b 第二个BigDecimal
     * @param roundingMode 舍入模式（如截断、四舍五入等）
     * @return 若小数点后两位及以上相等则返回true，否则返回false
     */
    public static boolean isEqualUpToTwoDecimals(BigDecimal a, BigDecimal b, RoundingMode roundingMode) {
        // 处理null情况：都为null则相等，否则不等
        if (a == null || b == null) {
            return a == b;
        }
        // 统一保留两位小数
        BigDecimal aScaled = a.setScale(2, roundingMode);
        BigDecimal bScaled = b.setScale(2, roundingMode);
        // 比较处理后的结果
        return aScaled.compareTo(bScaled) == 0;
    }


    /**
     * 激活采购计划
     * @param uc
     * @param bindId
     * @return
     */
    @Mapping("com.awspaas.user.apps.donenow_ivt.ivt_reactivate_pu")
    public ResponseObject reactivate_pu(UserContext uc, String bindId) {
        if (StringUtils.isBlank(bindId))
            return ResponseObject.newErrResponse("参数错误");
        if (SDK.getProcessAPI().isEndById(bindId)) {

            //未进行 过接收才能 复活
            if (DBSql.getInt("SELECT COUNT(a.ID) FROM BO_EU_DNIVT_RECEIVE_SUB a JOIN bo_eu_dnivt_order_product b ON a.ORDER_PRODUCT_ID=b.ID JOIN BO_EU_DNIVT_ORDER c ON b.BINDID=c.BINDID OR b.ORDER_ID=c.ID WHERE c.BINDID=? ", new Object[]{bindId}) > 0)
                return ResponseObject.newErrResponse("已进行接收操作，不允许再复活流程！");

            //如果 关联的服务进行了 付款 也不能 复活
            if (DBSql.getInt("SELECT COUNT(a.ID)  FROM BO_EU_DNIVT_ORDER_PAYMENT_PLAN a JOIN BO_EU_DNIVT_ORDER b ON a.ORDER_ID=b.ID WHERE b.BINDID=? AND a.PAY_AMOUNT<>0 and a.PAY_AMOUNT is not NULL ", new Object[]{bindId}) > 0)
                return ResponseObject.newErrResponse("进行了付款操作，不允许再复活流程！");

            SDK.getProcessAPI().reactivateById(bindId, "obj_bfa9227717bb41d69161f1ae8152d9ce", false, uc.getUID(), uc.getUID(), null);

            DBSql.update("update BO_EU_DNIVT_ORDER set STATUS_ID=? where BINDID=?", new Object[]{"2147", bindId});

        } else {
            return ResponseObject.newErrResponse("流程未结束");
        }
        return ResponseObject.newOkResponse();
    }


}
