package nccloud.api.impl.so.m30;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import nc.bd.itf.tools.BFPubTools;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.bs.trade.business.HYSuperDMO;
import nc.impl.pubapp.pattern.data.bill.BillQuery;
import nc.itf.scmpub.reference.uap.bd.customer.CustomerPubService;
import nc.itf.scmpub.reference.uap.pf.PfServiceScmUtil;
import nc.itf.so.m30.self.ISaleOrderMaintain;
import nc.itf.so.m30.self.ISaleOrderScriptMaintain;
import nc.itf.uap.IUAPQueryBS;
import nc.itf.uap.pf.IPFBusiAction;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.pubimpl.so.m30.pub.SaleOrderSaveUtil;
import nc.pubitf.so.m30.api.ISaleOrderQueryAPI;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.BusinessException;
import nc.vo.pub.VOStatus;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.calculator.HslParseUtil;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.scmpub.check.billvalidate.BillVOsCheckRule;
import nc.vo.scmpub.fill.pricemny.INumPriceMnyCalculator;
import nc.vo.scmpub.res.billtype.SOBillType;
import nc.vo.scmpub.util.CollectionUtils;
import nc.vo.scmpub.util.StringUtil;
import nc.vo.so.m30.entity.SaleOrderBVO;
import nc.vo.so.m30.entity.SaleOrderHVO;
import nc.vo.so.m30.entity.SaleOrderVO;
import nc.vo.so.pub.SOConstant;
import nc.vo.so.pub.enumeration.BillStatus;
import nc.vo.so.pub.keyvalue.IKeyValue;
import nc.vo.so.pub.keyvalue.VOKeyValue;
import nc.vo.so.pub.util.AggVOUtil;
import nccloud.api.impl.so.m30.check.SaleOrderValidator;
import nccloud.api.impl.so.m30.fill.SaleOrderNPriceMnyCal;
import nccloud.api.impl.so.m30.fill.SaleOrderSaveFillValue;
import nccloud.api.so.m30.IAPISaleOrderMaitain;
import nccloud.baseapp.core.log.NCCForUAPLogger;
import nccloud.commons.lang.StringUtils;
import nccloud.openapi.scmpub.pub.TransferCodeToPKTool;
import nccloud.openapi.scmpub.pub.TransferMapToVOTool;
import nccloud.putitf.riart.billtype.IBilltypeService;
import org.apache.commons.lang3.ArrayUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.zip.GZIPInputStream;

/**
 * @Description: 销售订单维护实现类
 * @author: yanghff
 * @date: 2019-10-23 下午4:57:49
 * @Copyright:
 */
public class APISaleOrderMaitainImpl implements IAPISaleOrderMaitain {
    private static String BODYTABLE = "so_saleorder_b";
    private static String HEADTABLE = "so_saleorder";

    public BaseDAO dao;

    public BaseDAO getDao() {
        if (dao == null) {
            dao = new BaseDAO();
        }
        return dao;
    }

    public SaleOrderVO[] save(SaleOrderVO[] vos) throws BusinessException {

        SaleOrderVO[] fillvos = vos;
        // 检查非空项
        for (SaleOrderVO vo : vos) {
            SaleOrderHVO hvo = vo.getParentVO();
            UFDate dbilldate = hvo.getDbilldate();
            SaleOrderBVO[] bvos = vo.getChildrenVO();
            String sql = " select bd_currtype.pk_currtype  from bd_currtype where (code='" + hvo.getCorigcurrencyid()
                    + "' or pk_currtype='" + hvo.getCorigcurrencyid() + "') and dr=0 ";
            Object o = getDao().executeQuery(sql, new ColumnProcessor());
            if (o != null) {
                hvo.setCorigcurrencyid(BFPubTools.getString_TrimAsNull(o));
            } else {
                throw new BusinessException("表头币种不能为空或币种不存在");
            }
            sql = " select bd_currtype.pk_currtype  from bd_currtype where (code='" + bvos[0].getCcurrencyid()
                    + "' or pk_currtype='" + bvos[0].getCcurrencyid() + "') and dr=0 ";
            Object o1 = getDao().executeQuery(sql, new ColumnProcessor());
            if (o1 == null) {
                throw new BusinessException("表体币种不能为空或币种不存在");
            }
            // String csettleorgid = bvos[0].getCsettleorgid();
            String ccurrencyorgid = o1.toString();
            // UFDouble exchangerate = SOCurrencyUtil.getInCurrencyRateByOrg(csettleorgid, BFPubTools.getString_TrimAsNull(o), ccurrencyorgid, dbilldate);
            for (SaleOrderBVO bvo : bvos) {
                bvo.setCcurrencyid(BFPubTools.getString_TrimAsNull(o1));
                if (!BFPubTools.getString_TrimAsNull(o).equals(ccurrencyorgid)) {
                    // bvo.setNexchangerate(exchangerate);
                } else {
                    // bvo.setNexchangerate(UFDouble.ONE_DBL);
                }
                // 折本汇率判空及保留小数位数
                UFDouble exchangerate1 = getUFDouble_NullAsOne(bvo.getNexchangerate()).setScale(2, UFDouble.ROUND_HALF_UP);
                bvo.setNexchangerate(exchangerate1);
            }
        }


        BillVOsCheckRule checker = new BillVOsCheckRule(new SaleOrderValidator());
        checker.check(vos);
        Map<String, String> origcurrencyMap = new HashMap<>();
        for (SaleOrderVO vo : vos) {
            SaleOrderHVO hvo = vo.getParentVO();
            String vbillcode = hvo.getVbillcode();
            String corigcurrencyid = hvo.getCorigcurrencyid();
            origcurrencyMap.put(vbillcode, corigcurrencyid);
        }
        // 填充默认值,重写setDefValue方法，去掉其中的价格金额计算
        new SaleOrderSaveFillValue().setDefValue1(vos);
        // 填充默认值的时候原币的值被覆盖，重新赋值为合同平台传过来的币种
        for (SaleOrderVO ordervo : vos) {
            SaleOrderHVO hvo = ordervo.getParentVO();
            String vbillcode = hvo.getVbillcode();
            if (origcurrencyMap.get(vbillcode) != null && !"".equals(origcurrencyMap.get(vbillcode))) {
                hvo.setCorigcurrencyid(origcurrencyMap.get(vbillcode));
            }
            calculatorPrice(ordervo);
        }
        // 有值不覆盖
        SaleOrderVO[] combinBillVOs = (SaleOrderVO[]) AggVOUtil.combinBillVO(fillvos, vos);
        // 保存
        SaleOrderVO[] retvos = (SaleOrderVO[]) PfServiceScmUtil.processBatch(SOConstant.WRITE,
                SOBillType.Order.getCode(), combinBillVOs, null, null);

        SaleOrderVO[] billvos = ((ISaleOrderQueryAPI) NCLocator.getInstance().lookup(ISaleOrderQueryAPI.class))
                .queryVOByIDs(new String[]{retvos[0].getParentVO().getPrimaryKey()});
        if (billvos != null) {
            ((IPFBusiAction) NCLocator.getInstance().lookup(IPFBusiAction.class)).processAction("APPROVE",
                    billvos[0].getParentVO().getVtrantypecode(), null, billvos[0], null, null);
        }
        return retvos;
    }

    public void calculatorPrice(SaleOrderVO ordervo) throws BusinessException {

        IKeyValue keyValue = new VOKeyValue<SaleOrderVO>(ordervo);

        String ctrantypeid = keyValue.getHeadStringValue(SaleOrderHVO.CTRANTYPEID);
        if (StringUtil.isEmptyTrimSpace(ctrantypeid)) {
            ExceptionUtils.wrappBusinessException(
                    NCLangRes4VoTransl.getNCLangRes().getStrByID("4006013_0", "04006013-0024")/* @res "请先选择交易类型！" */);
        }

        SaleOrderBVO[] vbos = ordervo.getChildrenVO();
        UFDouble sumnum = UFDouble.ZERO_DBL;
        UFDouble sumnny = UFDouble.ZERO_DBL;

        for (int i = 0; i < vbos.length; i++) {
            SaleOrderBVO childrenVO = vbos[i];
            childrenVO.setFtaxtypeflag(1);
            UFDouble nexchangerate = getUFDouble_NullAsOne(childrenVO.getNexchangerate());
            childrenVO.setNexchangerate(nexchangerate);
            // 处理数量、单价(4位)和金额(2位)
            // 含税单价
            UFDouble nqtorigtaxprice = childrenVO.getNqtorigtaxprice();
            nqtorigtaxprice = nqtorigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtorigtaxprice(nqtorigtaxprice);
            // 无税单价
            UFDouble nqtorigprice = childrenVO.getNqtorigprice();
            nqtorigprice = nqtorigprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtorigprice(nqtorigprice);
            // 含税净价
            UFDouble nqtorigtaxnetprc = childrenVO.getNqtorigtaxnetprc();
            nqtorigtaxnetprc = nqtorigtaxnetprc.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtorigtaxnetprc(nqtorigtaxnetprc);
            // 无税净价
            UFDouble nqtorignetprice = childrenVO.getNqtorignetprice();
            nqtorignetprice = nqtorignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtorignetprice(nqtorignetprice);
            // 主含税单价
            UFDouble norigtaxprice = childrenVO.getNorigtaxprice();
            norigtaxprice = norigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorigtaxprice(norigtaxprice);
            // 主无税单价
            UFDouble norigprice = childrenVO.getNorigprice();
            norigprice = norigprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorigprice(norigprice);
            // 主含税净价
            UFDouble norigtaxnetprice = childrenVO.getNorigtaxnetprice();
            norigtaxnetprice = norigtaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorigtaxnetprice(norigtaxnetprice);
            // 主无税净价
            UFDouble norignetprice = childrenVO.getNorignetprice();
            norignetprice = norignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorignetprice(norignetprice);
            // 本币无税金额
            UFDouble nmny = childrenVO.getNmny();
            nmny = nmny.setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNmny(nmny);
            childrenVO.setNcaltaxmny(nmny);// 计税金额
            // 本币价税合计
            UFDouble ntaxmny = childrenVO.getNtaxmny();
            ntaxmny = ntaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNtaxmny(ntaxmny);
            // 税额
            UFDouble ntax = childrenVO.getNtax();
            ntax = ntax.setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNtax(ntax);
            // 无税金额
            UFDouble norigmny = childrenVO.getNorigmny();
            norigmny = norigmny.setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorigmny(norigmny);
            // 价税合计
            UFDouble norigtaxmny = childrenVO.getNorigtaxmny();
            norigtaxmny = norigtaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNorigtaxmny(norigtaxmny);
            // 本币含税单价
            UFDouble nqttaxprice = childrenVO.getNqttaxprice();
            nqttaxprice = nqttaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqttaxprice(nqttaxprice);
            // 本币无税单价
            UFDouble nqtprice = childrenVO.getNqtprice();
            nqtprice = nqtprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtprice(nqtprice);
            // 本币含税净价
            UFDouble nqttaxnetprice = childrenVO.getNqttaxnetprice();
            nqttaxnetprice = nqttaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqttaxnetprice(nqttaxnetprice);
            // 本币无税净价
            UFDouble nqtnetprice = childrenVO.getNqtnetprice();
            nqtnetprice = nqtnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNqtnetprice(nqtnetprice);
            // 主本币含税单价
            UFDouble ntaxprice = childrenVO.getNtaxprice();
            ntaxprice = ntaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNtaxprice(ntaxprice);
            // 主本币无税单价
            UFDouble nprice = childrenVO.getNprice();
            nprice = nprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNprice(nprice);
            // 主本币含税净价
            UFDouble ntaxnetprice = childrenVO.getNtaxnetprice();
            ntaxnetprice = ntaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNtaxnetprice(ntaxnetprice);
            // 主本币无税净价
            UFDouble nnetprice = childrenVO.getNnetprice();
            nnetprice = nnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
            childrenVO.setNnetprice(nnetprice);
            Map<String, Object> goodsMap = getMaterlInfo(childrenVO.getCmaterialid());
            String measrate = "1/1";
            if (goodsMap != null && StringUtils.isEmpty(goodsMap.getOrDefault("measrate", "") + "")) {
                measrate = goodsMap.get("measrate") + "";
            }
            childrenVO.setVchangerate(measrate);// 换算率
            childrenVO.setVqtunitrate(measrate);// 报价换算率
            UFDouble[] measrateNums = HslParseUtil.parseHsl(measrate);
            UFDouble measrateNum = UFDouble.ONE_DBL;
            if (null != measrateNums && measrateNums.length != 0) {
                measrateNum = measrateNums[0].div(measrateNums[1]).setScale(2, 4);
            }
            // 主数量
            UFDouble nnum = childrenVO.getNnum().setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNnum(nnum);
            UFDouble nastnum = nnum.multiply(measrateNum).setScale(2, UFDouble.ROUND_HALF_UP);
            childrenVO.setNastnum(nastnum);// 数量
            childrenVO.setNqtunitnum(nastnum);// 报价单位数量
            sumnum = sumnum.add(nnum);
            sumnny = sumnny.add(norigtaxmny);

        }
        ordervo.getParentVO().setNtotalnum(sumnum);
        ordervo.getParentVO().setNtotalorigmny(sumnny.setScale(2, 4));
    }

    @Override
    public SaleOrderVO[] save(List<Map<String, Object>> paramList) throws BusinessException {
        try {
            List<SaleOrderVO> aggVOList = TransferMapToVOTool.transferMapToAggVO(paramList, SaleOrderVO.class);

            SaleOrderVO[] vos = (SaleOrderVO[]) aggVOList.toArray(new SaleOrderVO[aggVOList.size()]);
            BillVOsCheckRule checker = new BillVOsCheckRule(new SaleOrderValidator());
            checker.check(vos);

            aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);

            SaleOrderSaveUtil saveUtil = new SaleOrderSaveUtil();
            return saveUtil.processBill(vos);
        } catch (Exception e) {
            ExceptionUtils.marsh(e);
            return null;
        }
    }

    @Override
    public SaleOrderVO[] update(List<Map<String, Object>> paramList) throws BusinessException {
        List<SaleOrderVO> aggVOList = TransferMapToVOTool.transferMapToAggVO(paramList, SaleOrderVO.class);

        // aggVOList = TransferCodeToPKTool.transferAggVO(aggVOList);
        SaleOrderVO[] vos = (SaleOrderVO[]) aggVOList.toArray(new SaleOrderVO[aggVOList.size()]);
        setOtherId(vos);

        Map<String, Set<String>> ids = getIds(vos);
        if (ids.keySet() == null || ids.values() == null || ids.values().size() == 0) {
            ExceptionUtils.wrappBusinessException("请传入订单主键和订单行主键");
        }
        String[] hids = (String[]) ids.keySet().toArray(new String[ids.keySet().size()]);

        ISaleOrderMaintain service = (ISaleOrderMaintain) NCLocator.getInstance().lookup(ISaleOrderMaintain.class);
        SaleOrderVO[] originVos = service.querySaleorder(hids);
        if (null == originVos || originVos.length == 0) {
            ExceptionUtils.wrappBusinessException("根据传入数据未匹配到相关数据");
        }
        Map<String, List<String>> delBipMap = new HashMap<>();
        for (Map<String, Object> objectMap : paramList) {
            Map<String, Object> headdata = (Map<String, Object>) objectMap.get(HEADTABLE);
            String csaleorderid = headdata.get("csaleorderid") + "";
            List<Object> bodyArr = (List<Object>) objectMap.get(BODYTABLE);
            List<String> delIds = new ArrayList<>();
            for (Object body : bodyArr) {
                Map<String, Object> bodydata = (Map<String, Object>) body;
                if ((bodydata.getOrDefault("vbdef11", "") + "").isEmpty()) {
                    // 如果vbdef11为空则标记为新增行
                    bodydata.put("status", "add");
                }
                if (!(bodydata.getOrDefault("csaleorderbid", "") + "").isEmpty()) {
                    delIds.add(bodydata.get("csaleorderbid") + "");
                }
            }
            if (!delIds.isEmpty()) {
                delBipMap.put(csaleorderid, delIds);
            }
        }

        // SetUpdateData setData = new SetUpdateData();
        // setData.setData(vos, originVos);
        // SaleOrderVO[] combinBillVOs = (SaleOrderVO[]) AggVOUtil.combinBillVO(vos,
        // originVos);
        // 创建一个新的数组，并进行深拷贝
        SaleOrderVO[] combinBillVOs = new SaleOrderVO[originVos.length];
        for (int i = 0; i < originVos.length; i++) {
            combinBillVOs[i] = (SaleOrderVO) originVos[i].clone();
        }
        // 将 vos 中的元素按主键存储在 Map 中
        Map<String, SaleOrderVO> vosMap = new HashMap<>();
        for (SaleOrderVO vo : vos) {
            vosMap.put(vo.getParentVO().getCsaleorderid(), vo);
        }

        // 遍历 combinBillVOs 并更新字段
        for (SaleOrderVO vo : combinBillVOs) {
            SaleOrderHVO hvo = vo.getParentVO();
            String primaryKey = hvo.getCsaleorderid();
            SaleOrderVO bipVo = vosMap.get(primaryKey);
            // 设置单据状态
            hvo.setStatus(VOStatus.UPDATED);
            List<String> bipIds = delBipMap.get(primaryKey);

            // 比较combinBillVOs中的BVO和vos中的BVO
            for (SaleOrderBVO bvo : vo.getChildrenVO()) {
                bvo.setStatus(VOStatus.DELETED);
                String csaleorderbid = bvo.getCsaleorderbid();
                // 设置物料行的状态,在bip传的数据中找到则修改
                if (bipIds != null && !bipIds.isEmpty()) {
                    // 明细行设置为修改状态
                    if (bipIds.contains(csaleorderbid)) {
                        bvo.setStatus(VOStatus.UPDATED);
                    }
                }
            }
            // 更新 combinBillVO 中的字段为 vos 中的值
            updateFields(vo, bipVo);
            // 设置新增的物料行
            if (paramList != null && !paramList.isEmpty()) {
                addBvo(combinBillVOs, paramList);
            }
        }
        // 联动计算
        INumPriceMnyCalculator cal = new SaleOrderNPriceMnyCal<SaleOrderVO>(combinBillVOs);
        cal.calculate();
        for (SaleOrderVO vo : combinBillVOs) {
            SaleOrderHVO hvo = vo.getParentVO();
            SaleOrderHVO originHvo = null;
            for (SaleOrderVO originVo : originVos) {
                if (hvo.getCsaleorderid().equals(originVo.getParentVO().getCsaleorderid())) {
                    originHvo = originVo.getParentVO();
                }
            }
            String new_ctrantypeid = hvo.getCtrantypeid();
            boolean isChangedTranType = false;// 订单类型不修改
            if (originHvo != null && new_ctrantypeid != null && !new_ctrantypeid.equals(originHvo.getCtrantypeid())) {
                isChangedTranType = true;
            }
            SaleOrderBVO[] bvos = vo.getChildrenVO();
            // 判断是否存在新增的子表
            boolean hasNewStatus = Arrays.stream(bvos).anyMatch(bvo -> bvo.getStatus() == VOStatus.NEW);
            // 新增子表或改订单类型的情况下不校验是否存在下游
            if (!hasNewStatus && !isChangedTranType) {
                String countSql = "SELECT count(1) FROM so_saleinvoice_b a"
                        + " LEFT JOIN so_saleinvoice b ON a.csaleinvoiceid = b.csaleinvoiceid"
                        + " WHERE b.fopposeflag = 0 AND nvl(b.dr, 0) = 0 and csrcid = '[csrcid]'  ";
                countSql = countSql.replace("[csrcid]", hvo.getCsaleorderid());
                Integer num = (Integer) getDao().executeQuery(countSql, new ColumnProcessor());
                if (num > 0) {
                    // fopposeflag 对冲标记 0=正常 1=已被对冲 2=对冲生成
                    ExceptionUtils.wrappBusinessException("下游存在未红冲完成的销售发票");
                    return null;
                }
            }
        }

        fillcustomervidbyoid(combinBillVOs);

        // 保存
        ISaleOrderScriptMaintain maintainsrv = NCLocator.getInstance().lookup(ISaleOrderScriptMaintain.class);
        SaleOrderVO[] retvos = maintainsrv.saleOrderUpdate(combinBillVOs, null, originVos);
        if (retvos != null) {
            // 同步修改流程生产订单的国网行项目号、国内采购订单号
            updatePmoBill(retvos);
        }
        return retvos;
    }

    private Map<String, Set<String>> getIds(SaleOrderVO[] vos) {
        Map<String, Set<String>> ids = new HashMap<String, Set<String>>();
        for (SaleOrderVO vo : vos) {
            String hid = vo.getParentVO().getCsaleorderid();
            Set<String> bids = new HashSet<String>();
            for (SaleOrderBVO bvo : vo.getChildrenVO()) {
                bids.add(bvo.getCsaleorderbid());
            }
            ids.put(hid, bids);
        }
        return ids;
    }

    private void setOtherId(SaleOrderVO[] vos) {
        for (SaleOrderVO vo : vos) {
            // 部门、业务员、开票客户编码转id
            SaleOrderHVO orderHVO = vo.getParentVO();
            String csaleorderid = orderHVO.getCsaleorderid();
            String cdeptvid = orderHVO.getCdeptvid();
            String cemployeeid = orderHVO.getCemployeeid();
            // 开票客户
            String cinvoicecustid = orderHVO.getCinvoicecustid();
            // 客户
            String ccustomerid = orderHVO.getCcustomerid();
            // 订单类型
            // String ctrantypeid = orderHVO.getAttributeValue("ctrantypeid") + "";
            String vtrantypecode = orderHVO.getVtrantypecode();
            // NCCForUAPLogger.debug("setOtherId-ccustomerid:" + ccustomerid + ",vtrantypecode:" + vtrantypecode);
            try {
                String sql = "";
                // 部门
                if (cdeptvid != null && !cdeptvid.isEmpty()) {
                    sql = " select pk_vid,pk_dept from org_dept where code = '[code]' ";
                    sql = sql.replace("[code]", cdeptvid);
                    Map deptMap = (Map) getDao().executeQuery(sql, new MapProcessor());
                    // NCCForUAPLogger.debug("APISaleOrderMaitainImpl-setOtherId-deptObj:" + deptMap);
                    if (deptMap != null && !deptMap.isEmpty()) {
                        if (!"".equals(deptMap.getOrDefault("pk_dept", "") + "")) {
                            orderHVO.setCdeptid(deptMap.getOrDefault("pk_dept", "") + "");
                        }
                        if (!"".equals(deptMap.getOrDefault("pk_vid", "") + "")) {
                            orderHVO.setCdeptvid(deptMap.getOrDefault("pk_vid", "") + "");
                        }
                    }
                }
                // 业务员
                if (cemployeeid != null && !cemployeeid.isEmpty()) {
                    sql = " select pk_psndoc from bd_psndoc where code = '[code]' ";
                    sql = sql.replace("[code]", cemployeeid);
                    Object staffObj = getDao().executeQuery(sql, new ColumnProcessor("pk_psndoc"));
                    // NCCForUAPLogger.debug("APISaleOrderMaitainImpl-setOtherId-staffObj:" + staffObj);
                    if (staffObj != null) {
                        String id = BFPubTools.getString_TrimAsNull(staffObj);
                        if (!id.isEmpty()) {
                            orderHVO.setCemployeeid(id);
                        }
                    }
                }
                // 开票客户
                if (cinvoicecustid != null && !cinvoicecustid.isEmpty()) {
                    sql = " select pk_customer from bd_customer where nvl(dr,0) = 0 and code = '[code]' ";
                    sql = sql.replace("[code]", cinvoicecustid);
                    Object invCustObj = getDao().executeQuery(sql, new ColumnProcessor("pk_customer"));
                    // NCCForUAPLogger.debug("setOtherId-invCustObj:" + invCustObj);
                    if (invCustObj != null) {
                        String id = BFPubTools.getString_TrimAsNull(invCustObj);
                        if (!id.isEmpty()) {
                            orderHVO.setCinvoicecustid(id);
                        }
                    }
                }
                // 客户
                if (ccustomerid != null && !ccustomerid.isEmpty()) {
                    sql = " select pk_customer from bd_customer where nvl(dr,0) = 0 and code = '[code]' ";
                    sql = sql.replace("[code]", ccustomerid);
                    Object custObj = getDao().executeQuery(sql, new ColumnProcessor("pk_customer"));
                    // NCCForUAPLogger.debug("setOtherId-custObj:" + custObj);
                    if (custObj != null) {
                        String id = BFPubTools.getString_TrimAsNull(custObj);
                        if (!id.isEmpty()) {
                            orderHVO.setCcustomerid(id);
                        }
                    }
                }
                // 交易类型
                if (vtrantypecode != null && !vtrantypecode.isEmpty()) {
                    IBilltypeService billtypeService = NCLocator.getInstance().lookup(IBilltypeService.class);
                    BilltypeVO billtype = billtypeService.getBilltype(vtrantypecode);
                    if (billtype != null && billtype.getPk_billtypeid() != null) {
                        // NCCForUAPLogger.debug("setOtherId-pk_billtypeid:" + billtype.getPk_billtypeid());
                        orderHVO.setCtrantypeid(billtype.getPk_billtypeid());
                    }
                }
            } catch (Exception e) {
                Logger.error("APISaleOrderMaitainImpl-setOtherId-exp:" + e.getMessage());
                throw new RuntimeException(e);
            }
        }
    }

    private void updateFields(SaleOrderVO target, SaleOrderVO source) throws BusinessException {
        // 更新 SaleOrderHVO 字段
        SaleOrderHVO targetHVO = target.getParentVO();
        SaleOrderHVO sourceHVO = source.getParentVO();
        // 表头修改修改的字段
        String cdeptvid = sourceHVO.getCdeptvid();
        String cdeptid = sourceHVO.getCdeptid();
        if (cdeptvid != null && !cdeptvid.isEmpty()) {
            targetHVO.setCdeptvid(cdeptvid);
            targetHVO.setCdeptid(cdeptid);
        }

        String cemployeeid = sourceHVO.getCemployeeid();
        if (cemployeeid != null && !cemployeeid.isEmpty()) {
            targetHVO.setCemployeeid(cemployeeid);
        }
        String cinvoicecustid = sourceHVO.getCinvoicecustid();
        if (cinvoicecustid != null && !cinvoicecustid.isEmpty()) {
            targetHVO.setCinvoicecustid(cinvoicecustid);
            targetHVO.setCinvoicecustvid(cinvoicecustid);
        }
        String ccustomerid = sourceHVO.getCcustomerid();
        if (ccustomerid != null && !ccustomerid.isEmpty()) {
            targetHVO.setCcustomerid(ccustomerid);
            targetHVO.setCcustomervid(ccustomerid);
        }
        // 订单类型id
        String ctrantypeid = sourceHVO.getCtrantypeid();
        if (ctrantypeid != null && !ctrantypeid.isEmpty()) {
            targetHVO.setCtrantypeid(ctrantypeid);
        }
        // 订单类型编码
        String vtrantypecode = sourceHVO.getVtrantypecode();
        if (vtrantypecode != null && !vtrantypecode.isEmpty()) {
            targetHVO.setVtrantypecode(vtrantypecode);
        }
        // 订单关联合同号

        String vdef19 = sourceHVO.getVdef19();
        if (vdef19 != null && !vdef19.isEmpty()) {
            targetHVO.setVdef19(vdef19);
        }

        // 工程名称
        String vdef20 = sourceHVO.getVdef20();
        if (vdef20 != null && !vdef20.isEmpty()) {
            targetHVO.setVdef20(vdef20);
        }

        // 更新 SaleOrderBVO 字段
        SaleOrderBVO[] targetBVOs = target.getChildrenVO();
        SaleOrderBVO[] sourceBVOs = source.getChildrenVO();

        // BVO 的主键是 csaleorderbid
        Map<String, SaleOrderBVO> sourceBVOsMap = new HashMap<>();
        for (SaleOrderBVO bvo : sourceBVOs) {
            sourceBVOsMap.put(bvo.getCsaleorderbid(), bvo);
        }

        for (SaleOrderBVO targetBVO : targetBVOs) {
            String bvoId = targetBVO.getCsaleorderbid();
            SaleOrderBVO sourceBVO = sourceBVOsMap.get(bvoId);
            if (sourceBVO != null) {
                int status = targetBVO.getStatus();
                if (VOStatus.UPDATED == status) {
                    // 是否赠品
                    targetBVO.setBlargessflag(sourceBVO.getBlargessflag());
                    // 折本汇率
                    UFDouble nexchangerate = getUFDouble_NullAsOne(sourceBVO.getNexchangerate());
                    targetBVO.setNexchangerate(nexchangerate);
                    // 物料编码
                    targetBVO.setCmaterialvid(sourceBVO.getCmaterialvid());
                    String cmaterialvid = sourceBVO.getCmaterialvid();
                    // 物料关联字段赋值
                    if (cmaterialvid != null && !cmaterialvid.isEmpty()) {
                        setMaterl(targetBVO);
                    }
                    // 处理数量、单价(4位)和金额(2位)
                    // 含税单价
                    UFDouble nqtorigtaxprice = sourceBVO.getNqtorigtaxprice();
                    nqtorigtaxprice = nqtorigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtorigtaxprice(nqtorigtaxprice);
                    // 无税单价
                    UFDouble nqtorigprice = sourceBVO.getNqtorigprice();
                    nqtorigprice = nqtorigprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtorigprice(nqtorigprice);
                    // 含税净价
                    UFDouble nqtorigtaxnetprc = sourceBVO.getNqtorigtaxnetprc();
                    nqtorigtaxnetprc = nqtorigtaxnetprc.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtorigtaxnetprc(nqtorigtaxnetprc);
                    // 无税净价
                    UFDouble nqtorignetprice = sourceBVO.getNqtorignetprice();
                    nqtorignetprice = nqtorignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtorignetprice(nqtorignetprice);
                    // 主含税单价
                    UFDouble norigtaxprice = sourceBVO.getNorigtaxprice();
                    norigtaxprice = norigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorigtaxprice(norigtaxprice);
                    // 主无税单价
                    UFDouble norigprice = sourceBVO.getNorigprice();
                    norigprice = norigprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorigprice(norigprice);
                    // 主含税净价
                    UFDouble norigtaxnetprice = sourceBVO.getNorigtaxnetprice();
                    norigtaxnetprice = norigtaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorigtaxnetprice(norigtaxnetprice);
                    // 主无税净价
                    UFDouble norignetprice = sourceBVO.getNorignetprice();
                    norignetprice = norignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorignetprice(norignetprice);
                    // 本币无税金额
                    UFDouble nmny = sourceBVO.getNmny();
                    nmny = nmny.setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNmny(nmny);
                    targetBVO.setNcaltaxmny(nmny);// 计税金额
                    // 本币价税合计
                    UFDouble ntaxmny = sourceBVO.getNtaxmny();
                    ntaxmny = ntaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNtaxmny(ntaxmny);
                    // 税额
                    UFDouble ntax = sourceBVO.getNtax();
                    ntax = ntax.setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNtax(ntax);
                    // 无税金额
                    UFDouble norigmny = sourceBVO.getNorigmny();
                    norigmny = norigmny.setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorigmny(norigmny);
                    // 价税合计
                    UFDouble norigtaxmny = sourceBVO.getNorigtaxmny();
                    norigtaxmny = norigtaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNorigtaxmny(norigtaxmny);
                    // 本币含税单价
                    UFDouble nqttaxprice = sourceBVO.getNqttaxprice();
                    nqttaxprice = nqttaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqttaxprice(nqttaxprice);
                    // 本币无税单价
                    UFDouble nqtprice = sourceBVO.getNqtprice();
                    nqtprice = nqtprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtprice(nqtprice);
                    // 本币含税净价
                    UFDouble nqttaxnetprice = sourceBVO.getNqttaxnetprice();
                    nqttaxnetprice = nqttaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqttaxnetprice(nqttaxnetprice);
                    // 本币无税净价
                    UFDouble nqtnetprice = sourceBVO.getNqtnetprice();
                    nqtnetprice = nqtnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNqtnetprice(nqtnetprice);
                    // 主本币含税单价
                    UFDouble ntaxprice = sourceBVO.getNtaxprice();
                    ntaxprice = ntaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNtaxprice(ntaxprice);
                    // 主本币无税单价
                    UFDouble nprice = sourceBVO.getNprice();
                    nprice = nprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNprice(nprice);
                    // 主本币含税净价
                    UFDouble ntaxnetprice = sourceBVO.getNtaxnetprice();
                    ntaxnetprice = ntaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNtaxnetprice(ntaxnetprice);
                    // 主本币无税净价
                    UFDouble nnetprice = sourceBVO.getNnetprice();
                    nnetprice = nnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNnetprice(nnetprice);
                    String measrate = "1/1";
                    if (StringUtils.isNotEmpty(targetBVO.getVchangerate())) {
                        measrate = targetBVO.getVchangerate();
                    }
                    // targetBVO.setVchangerate(measrate);// 换算率
                    // targetBVO.setVqtunitrate(measrate);// 报价换算率
                    UFDouble[] measrateNums = HslParseUtil.parseHsl(measrate);
                    UFDouble measrateNum = UFDouble.ONE_DBL;
                    if (null != measrateNums && measrateNums.length != 0) {
                        measrateNum = measrateNums[0].div(measrateNums[1]).setScale(2, 4);
                    }
                    // 主数量
                    UFDouble nnum = sourceBVO.getNnum().setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNnum(nnum);
                    UFDouble nastnum = nnum.multiply(measrateNum).setScale(2, UFDouble.ROUND_HALF_UP);
                    targetBVO.setNastnum(nastnum);// 数量
                    targetBVO.setNqtunitnum(nastnum);// 报价单位数量

                    // 自定义项赋值
                    String vbdef1 = sourceBVO.getVbdef1();// 合同编号
                    Map<String, String> defList = getDefList("zdy-001");
                    targetBVO.setVbdef1(defList.getOrDefault(vbdef1, ""));
                    String vbdef5 = sourceBVO.getVbdef5();// 合同销售订单号
                    defList.clear();
                    defList = getDefList("BIP-ddh");
                    targetBVO.setVbdef5(defList.getOrDefault(vbdef5, ""));
                    // 新增字段的setter方法
                    targetBVO.setVbdef10(sourceBVO.getVbdef10());  // 项目名称
                    targetBVO.setVbdef13(sourceBVO.getVbdef13());  // 国网行项目号
                    targetBVO.setVbdef14(sourceBVO.getVbdef14());  // 合同销售订单变更明细id
                    targetBVO.setVbdef18(sourceBVO.getVbdef18());  // 是否定制
                    targetBVO.setVbdef22(sourceBVO.getVbdef22());  // 国内采购订单号
                    if (StringUtils.isNotEmpty(sourceBVO.getCrowno())) {
                        targetBVO.setCrowno(sourceBVO.getCrowno());  // 行号
                    }
                    if (StringUtils.isNotEmpty(sourceBVO.getVbdef19())) {
                        targetBVO.setVbdef19(sourceBVO.getVbdef19());  // 计划开工日期
                    }
                    if (StringUtils.isNotEmpty(sourceBVO.getVbdef20())) {
                        targetBVO.setVbdef20(sourceBVO.getVbdef20());  // 计划完工日期
                    }

                }

            }
        }
    }

    /**
     * 获取自定义项信息
     */
    private Map<String, String> getDefList(String code) {
        Map<String, String> map = new HashMap<String, String>();
        String strWhere = " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='" + code
                + "' and dr=0 )  and dr = 0";
        try {
            DefdocVO[] defdocVOs = (DefdocVO[]) new HYSuperDMO().queryByWhereClause(DefdocVO.class, strWhere);
            if (defdocVOs != null && defdocVOs.length > 0) {
                for (DefdocVO defdocVO : defdocVOs) {
                    map.put(defdocVO.getCode().trim(), defdocVO.getPk_defdoc());
                }
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return map;

    }

    @Override
    public void delete(String[] hids) throws BusinessException {
        BillQuery<SaleOrderVO> queryTool = new BillQuery<SaleOrderVO>(SaleOrderVO.class);
        SaleOrderVO[] saleOrderVOs = (SaleOrderVO[]) queryTool.query(hids);
        if (saleOrderVOs.length == 0) {
            ExceptionUtils.wrappBusinessException("根据传入数据未匹配到相关数据");
        }

        PfServiceScmUtil.processBatch("DELETE", SOBillType.Order.getCode(), saleOrderVOs, null, null);
    }

    private void fillcustomervidbyoid(SaleOrderVO[] combinBillVOs) {
        Set<String> customeridSet = new HashSet<String>();
        Map<String, String> customeridMap = new HashMap<String, String>();
        for (SaleOrderVO vo : combinBillVOs) {
            SaleOrderHVO hvo = vo.getParentVO();

            if (!StringUtil.isSEmptyOrNull(hvo.getCcustomerid()) && StringUtil.isSEmptyOrNull(hvo.getCcustomervid())) {
                customeridSet.add(hvo.getCcustomerid());
            }

            if (!StringUtil.isSEmptyOrNull(hvo.getCinvoicecustid())
                    && StringUtil.isSEmptyOrNull(hvo.getCinvoicecustvid())) {
                customeridSet.add(hvo.getCinvoicecustid());
            }

            if (!StringUtil.isSEmptyOrNull(hvo.getChreceivecustid())
                    && StringUtil.isSEmptyOrNull(hvo.getChreceivecustvid())) {
                customeridSet.add(hvo.getChreceivecustid());
            }

            SaleOrderBVO[] bvos = vo.getChildrenVO();
            for (SaleOrderBVO bvo : bvos) {

                if (!StringUtil.isSEmptyOrNull(bvo.getCreceivecustid())
                        && StringUtil.isSEmptyOrNull(bvo.getCreceivecustvid())) {
                    customeridSet.add(bvo.getCreceivecustid());
                }

                if (!StringUtil.isSEmptyOrNull(bvo.getCvendorid()) && StringUtil.isSEmptyOrNull(bvo.getCvendorvid())) {
                    customeridSet.add(bvo.getCvendorid());
                }
            }
        }

        if (!customeridSet.isEmpty()) {
            customeridMap = CustomerPubService
                    .queryCustomerVidsByOids((String[]) CollectionUtils.setToArray(customeridSet));
        }

        for (SaleOrderVO vo : combinBillVOs) {
            SaleOrderHVO hvo = vo.getParentVO();

            if (!StringUtil.isSEmptyOrNull(hvo.getCcustomerid()) && StringUtil.isSEmptyOrNull(hvo.getCcustomervid())) {
                if (null == customeridMap || customeridMap.size() == 0) {
                    hvo.setCcustomervid(hvo.getCcustomerid());
                } else {
                    hvo.setCcustomervid((String) customeridMap.get(hvo.getCcustomerid()));
                }
            }

            if (!StringUtil.isSEmptyOrNull(hvo.getCinvoicecustid())
                    && StringUtil.isSEmptyOrNull(hvo.getCinvoicecustvid())) {
                if (null == customeridMap || customeridMap.size() == 0) {
                    hvo.setCinvoicecustvid(hvo.getCinvoicecustid());
                } else {
                    hvo.setCinvoicecustvid((String) customeridMap.get(hvo.getCinvoicecustid()));
                }
            }

            if (!StringUtil.isSEmptyOrNull(hvo.getChreceivecustid())
                    && StringUtil.isSEmptyOrNull(hvo.getChreceivecustvid())) {
                if (null == customeridMap || customeridMap.size() == 0) {
                    hvo.setChreceivecustvid(hvo.getChreceivecustid());
                } else {
                    hvo.setChreceivecustvid((String) customeridMap.get(hvo.getChreceivecustid()));
                }
            }

            SaleOrderBVO[] bvos = vo.getChildrenVO();
            for (SaleOrderBVO bvo : bvos) {

                if (!StringUtil.isSEmptyOrNull(bvo.getCreceivecustid())
                        && StringUtil.isSEmptyOrNull(bvo.getCreceivecustvid())) {
                    if (null == customeridMap || customeridMap.size() == 0) {
                        bvo.setCreceivecustvid(bvo.getCreceivecustid());
                    } else {
                        bvo.setCreceivecustvid((String) customeridMap.get(bvo.getCreceivecustid()));
                    }
                }

                if (!StringUtil.isSEmptyOrNull(bvo.getCvendorid()) && StringUtil.isSEmptyOrNull(bvo.getCvendorvid())) {
                    if (null == customeridMap || customeridMap.size() == 0) {
                        bvo.setCvendorvid(bvo.getCvendorid());
                    } else {
                        bvo.setCvendorvid((String) customeridMap.get(bvo.getCvendorid()));
                    }
                }
            }
        }
    }

    @Override
    public SaleOrderVO[] sendApprove(String[] hids) throws BusinessException {
        SaleOrderVO[] vos = querySaleOrder(hids);
        try {
            for (SaleOrderVO aggvo : vos) {
                SaleOrderHVO parentVO = aggvo.getParentVO();
                if (!BillStatus.FREE.equalsValue(parentVO.getFstatusflag())) {
                    ExceptionUtils.wrappBusinessException("当前销售订单：" + parentVO.getVbillcode() + "不是自由状态，不能提交");
                }
            }
            return (SaleOrderVO[]) PfServiceScmUtil.processBatch("SAVE", SOBillType.Order.getCode(), vos, null, null);
        } catch (Exception e) {
            ExceptionUtils.marsh(e);
            return null;
        }
    }

    @Override
    public SaleOrderVO[] unSendApprove(String[] hids) throws BusinessException {
        SaleOrderVO[] vos = querySaleOrder(hids);
        try {
            for (SaleOrderVO aggvo : vos) {
                SaleOrderHVO parentVO = aggvo.getParentVO();
                if (!BillStatus.AUDITING.equalsValue(parentVO.getFstatusflag())) {
                    ExceptionUtils.wrappBusinessException("当前销售订单：" + parentVO.getVbillcode() + "不是提交状态，不能收回");
                }
            }
            return (SaleOrderVO[]) PfServiceScmUtil.processBatch("UNSAVE", SOBillType.Order.getCode(), vos, null, null);
        } catch (Exception e) {
            ExceptionUtils.marsh(e);
            return null;
        }
    }

    @Override
    public SaleOrderVO[] approve(String[] hids) throws BusinessException {
        SaleOrderVO[] vos = querySaleOrder(hids);
        try {
            for (SaleOrderVO aggvo : vos) {
                SaleOrderHVO parentVO = aggvo.getParentVO();
                if (!BillStatus.FREE.equalsValue(parentVO.getFstatusflag())
                        && !BillStatus.AUDIT.equalsValue(parentVO.getFstatusflag())
                        && !BillStatus.AUDITING.equalsValue(parentVO.getFstatusflag())) {
                    ExceptionUtils.wrappBusinessException("当前销售订单：" + parentVO.getVbillcode() + "状态不符合审批条件，不能审批");
                }
            }
            return (SaleOrderVO[]) PfServiceScmUtil.processBatch("APPROVE", SOBillType.Order.getCode(), vos, null,
                    null);
        } catch (Exception e) {
            ExceptionUtils.marsh(e);
            return null;
        }
    }

    @Override
    public SaleOrderVO[] unApprove(String[] hids) throws BusinessException {
        SaleOrderVO[] vos = querySaleOrder(hids);
        try {
            for (SaleOrderVO aggvo : vos) {
                SaleOrderHVO parentVO = aggvo.getParentVO();
                if (!BillStatus.AUDIT.equalsValue(parentVO.getFstatusflag())
                        && !BillStatus.AUDITING.equalsValue(parentVO.getFstatusflag())) {
                    ExceptionUtils.wrappBusinessException("当前销售订单：" + parentVO.getVbillcode() + "状态不符合弃审条件，不能弃审");
                }
            }
            return (SaleOrderVO[]) PfServiceScmUtil.processBatch("UNAPPROVE", SOBillType.Order.getCode(), vos, null,
                    null);
        } catch (Exception e) {
            ExceptionUtils.marsh(e);
            return null;
        }
    }

    private SaleOrderVO[] querySaleOrder(String[] hids) throws BusinessException {
        ISaleOrderQueryAPI service = (ISaleOrderQueryAPI) NCLocator.getInstance().lookup(ISaleOrderQueryAPI.class);
        SaleOrderVO[] vos = service.queryVOByIDs(hids);
        if (ArrayUtils.isEmpty(vos)) {
            ExceptionUtils.wrappBusinessException("没有符合条件的数据");
        } else {
            return vos;
        }
        return null;
    }

    /**
     * 设置物料的相关字段
     */
    private void setMaterl(SaleOrderBVO bVO) {
        String cmaterialvid = bVO.getCmaterialvid();
        // UFDouble nnum = bVO.getNnum();
        UFDouble ntaxrate = bVO.getNtaxrate();
        try {
            String sql = " select a.pk_material,a.pk_source, a.pk_measdoc cunitid,nvl(b.pk_measdoc,a.pk_measdoc) castunitid,nvl(b.measrate,'1/1') measrate "
                    + "from bd_material a left join bd_materialconvert  b on a.pk_material=b.pk_material "
                    + "where a.code='" + cmaterialvid + "'  ";
            Map map = (Map) getDao().executeQuery(sql, new MapProcessor());
            if (map == null) {
                throw new BusinessException(cmaterialvid + "物料未查到");
            }
            // NCCForUAPLogger.debug(String.format("setMaterl: cqtunitid = [%S], cunitid = [%S], castunitid = [%S]",
            //         map.get("cqtunitid"), map.get("cunitid"), map.get("castunitid")));
            bVO.setAttributeValue("castunitid", map.get("castunitid"));
            bVO.setAttributeValue("vchangerate", map.get("vchangerate"));

            // 重新计算金额
            bVO.setAttributeValue("cqtunitid", map.get("cunitid"));
            bVO.setAttributeValue("cunitid", map.get("cunitid"));

            bVO.setAttributeValue("cmaterialid", map.get("pk_material"));
            bVO.setAttributeValue("cmaterialvid", map.get("pk_material"));
            bVO.setVchangerate(map.get("measrate") + "");// 换算率
            bVO.setVqtunitrate(map.get("measrate") + "");// 报价换算率

            // UFDouble nqtunitnum = BFPubTools.getUFDouble_NullAsZero(nnum)
            //         .div(BFPubTools.getUFDouble_NullAsZero(map.get("measrate").toString().split("/")[0]));
            // bVO.setAttributeValue("nqtunitnum", nqtunitnum);

            sql = "select sl.pk_taxcode from bd_taxrate sl inner join bd_taxcode sm on sl.pk_taxcode=sm.pk_taxcode  where sl.taxrate="
                    + ntaxrate + " and sm.pk_group<>'~' ";

            String o_pk_project = (String) getDao().executeQuery(sql, new ColumnProcessor());
            // 税码
            bVO.setAttributeValue("ctaxcodeid", o_pk_project);
        } catch (BusinessException e) {
            Logger.error("APISaleOrderMaitainImpl-setMaterl:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取物料的信息
     *
     * @param pk_material
     * @return
     * @throws BusinessException
     */
    private Map<String, Object> getMaterlInfo(String pk_material) throws BusinessException {
        if (pk_material == null || pk_material.isEmpty()) {
            return null;
        }
        IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String sql = " select nvl(measrate, '1/1') measrate" +
                " from bd_materialconvert" +
                " where pk_material='" + pk_material + "' ";
        return (Map<String, Object>) queryBS.executeQuery(sql, new MapProcessor());
    }

    /**
     * 修订销售订单的时候新增销售订单物料行的数据
     */
    private void addBvo(SaleOrderVO[] oldVOs, List<Map<String, Object>> paramList) {
        try {
            SaleOrderVO[] copyVOs = new SaleOrderVO[oldVOs.length];
            for (int i = 0; i < oldVOs.length; i++) {
                copyVOs[i] = (SaleOrderVO) oldVOs[i].clone();
            }
            // 将 vos 中的元素按主键存储在 Map 中
            Map<String, SaleOrderVO> vosMap = new HashMap<>();
            for (SaleOrderVO vo : copyVOs) {
                vosMap.put(vo.getParentVO().getCsaleorderid(), vo);
            }
            for (Map<String, Object> objectMap : paramList) {
                Map<String, Object> headdata = (Map<String, Object>) objectMap.get("so_saleorder");
                String primaryKey = headdata.getOrDefault("csaleorderid", "") + "";
                SaleOrderVO vo = vosMap.get(primaryKey);
                SaleOrderHVO hvo = vo.getParentVO();
                String csaleorderid = hvo.getCsaleorderid();
                String ybpk = hvo.getCorigcurrencyid();
                SaleOrderBVO[] bvos = vo.getChildrenVO();
                List<SaleOrderBVO> bvoList = new ArrayList<>(Arrays.asList(bvos));
                SaleOrderBVO oneBvo = vo.getChildrenVO()[0];

                List<Object> bodyArr = (List<Object>) objectMap.get("so_saleorder_b");
                for (Object body : bodyArr) {
                    Map<String, Object> bodydata = (Map<String, Object>) body;
                    if ("add".equals(bodydata.get("status"))) {
                        String pk_group = AppContext.getInstance().getPkGroup();
                        // 新数据的实体
                        SaleOrderBVO newBvo = new SaleOrderBVO();
                        newBvo.setStatus(VOStatus.NEW);
                        newBvo.setAttributeValue("pk_group", pk_group);
                        String cprojectid = bodydata.get("cprojectid") + "";
                        if (oneBvo != null && oneBvo.getCprojectid() != null && !"".equals(oneBvo.getCprojectid())) {
                            cprojectid = oneBvo.getCprojectid();
                        } else {
                            String sql = " select pk_project from bd_project  where project_code='" + cprojectid
                                    + "'  and nvl(dr,0)=0  ";
                            cprojectid = (String) getDao().executeQuery(sql, new ColumnProcessor());
                        }
                        newBvo.setAttributeValue("cprojectid", cprojectid);

                        newBvo.setAttributeValue("ctaxcountryid", "CN");
                        newBvo.setAttributeValue("crececountryid", "CN");
                        newBvo.setAttributeValue("csendcountryid", "CN");

                        newBvo.setAttributeValue("fbuysellflag", 1);
                        // 折本汇率
                        UFDouble nexchangerateBip = getUFDouble_NullAsOne(bodydata.get("nexchangerate"));
                        newBvo.setNexchangerate(nexchangerateBip);
                        // 设置物料的关联字段的值
                        newBvo.setCmaterialvid(bodydata.get("cmaterialvid") + "");
                        UFDouble ntaxrate = BFPubTools.getUFDouble_NullAsZero(bodydata.get("ntaxrate"));
                        newBvo.setAttributeValue("ntaxrate", ntaxrate);
                        newBvo.setVbdef11(bodydata.getOrDefault("vbdef11", "") + "");
                        newBvo.setVbdef14(bodydata.getOrDefault("vbdef14", "") + "");
                        newBvo.setCsaleorderbid(null);
                        newBvo.setCcurrencyid(ybpk);
                        newBvo.setFtaxtypeflag(1);
                        // 行号
                        newBvo.setCrowno(bodydata.get("crowno") + "");
                        // 是否赠品
                        String blargessflag = bodydata.getOrDefault("blargessflag", "N") + "";
                        newBvo.setBlargessflag(UFBoolean.valueOf(blargessflag));

                        setMaterl(newBvo);

                        // 处理数量、单价(4位)和金额(2位)
                        // 含税单价
                        UFDouble nqtorigtaxprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtorigtaxprice"));
                        nqtorigtaxprice = nqtorigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtorigtaxprice(nqtorigtaxprice);
                        // 无税单价
                        UFDouble nqtorigprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtorigprice"));
                        nqtorigprice = nqtorigprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtorigprice(nqtorigprice);
                        // 含税净价
                        UFDouble nqtorigtaxnetprc = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtorigtaxnetprc"));
                        nqtorigtaxnetprc = nqtorigtaxnetprc.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtorigtaxnetprc(nqtorigtaxnetprc);
                        // 无税净价
                        UFDouble nqtorignetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtorignetprice"));
                        nqtorignetprice = nqtorignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtorignetprice(nqtorignetprice);
                        // 主含税单价
                        UFDouble norigtaxprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norigtaxprice"));
                        norigtaxprice = norigtaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorigtaxprice(norigtaxprice);
                        // 主无税单价
                        UFDouble norigprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norigprice"));
                        norigprice = norigprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorigprice(norigprice);
                        // 主含税净价
                        UFDouble norigtaxnetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norigtaxnetprice"));
                        norigtaxnetprice = norigtaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorigtaxnetprice(norigtaxnetprice);
                        // 主无税净价
                        UFDouble norignetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norignetprice"));
                        norignetprice = norignetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorignetprice(norignetprice);
                        // 本币无税金额
                        UFDouble nmny = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nmny"));
                        nmny = nmny.setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNmny(nmny);
                        newBvo.setNcaltaxmny(nmny);// 计税金额
                        // 本币价税合计
                        UFDouble ntaxmny = BFPubTools.getUFDouble_NullAsZero(bodydata.get("ntaxmny"));
                        ntaxmny = ntaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNtaxmny(ntaxmny);
                        // 税额
                        UFDouble ntax = BFPubTools.getUFDouble_NullAsZero(bodydata.get("ntax"));
                        ntax = ntax.setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNtax(ntax);
                        // 无税金额
                        UFDouble norigmny = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norigmny"));
                        norigmny = norigmny.setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorigmny(norigmny);
                        // 价税合计
                        UFDouble norigtaxmny = BFPubTools.getUFDouble_NullAsZero(bodydata.get("norigtaxmny"));
                        norigtaxmny = norigtaxmny.setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNorigtaxmny(norigtaxmny);
                        // 本币含税单价
                        UFDouble nqttaxprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqttaxprice"));
                        nqttaxprice = nqttaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqttaxprice(nqttaxprice);
                        // 本币无税单价
                        UFDouble nqtprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtprice"));
                        nqtprice = nqtprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtprice(nqtprice);
                        // 本币含税净价
                        UFDouble nqttaxnetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqttaxnetprice"));
                        nqttaxnetprice = nqttaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqttaxnetprice(nqttaxnetprice);
                        // 本币无税净价
                        UFDouble nqtnetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nqtnetprice"));
                        nqtnetprice = nqtnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNqtnetprice(nqtnetprice);
                        // 主本币含税单价
                        UFDouble ntaxprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("ntaxprice"));
                        ntaxprice = ntaxprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNtaxprice(ntaxprice);
                        // 主本币无税单价
                        UFDouble nprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nprice"));
                        nprice = nprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNprice(nprice);
                        // 主本币含税净价
                        UFDouble ntaxnetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("ntaxnetprice"));
                        ntaxnetprice = ntaxnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNtaxnetprice(ntaxnetprice);
                        // 主本币无税净价
                        UFDouble nnetprice = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nnetprice"));
                        nnetprice = nnetprice.setScale(4, UFDouble.ROUND_HALF_UP);
                        newBvo.setNnetprice(nnetprice);
                        String measrate = "1/1";
                        if (StringUtils.isNotEmpty(newBvo.getVchangerate())) {
                            measrate = newBvo.getVchangerate();
                        }
                        // newBvo.setVchangerate(measrate);// 换算率
                        // newBvo.setVqtunitrate(measrate);// 报价换算率
                        UFDouble[] measrateNums = HslParseUtil.parseHsl(measrate);
                        UFDouble measrateNum = UFDouble.ONE_DBL;
                        if (null != measrateNums && measrateNums.length != 0) {
                            measrateNum = measrateNums[0].div(measrateNums[1]).setScale(2, 4);
                        }
                        // 主数量
                        UFDouble nnum = BFPubTools.getUFDouble_NullAsZero(bodydata.get("nnum")).setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNnum(nnum);
                        UFDouble nastnum = nnum.multiply(measrateNum).setScale(2, UFDouble.ROUND_HALF_UP);
                        newBvo.setNastnum(nastnum);// 数量
                        newBvo.setNqtunitnum(nastnum);// 报价单位数量

                        // 自定义项赋值
                        String vbdef1 = bodydata.getOrDefault("vbdef1", "") + "";// 合同编号
                        Map<String, String> defList = getDefList("zdy-001");
                        newBvo.setVbdef1(defList.getOrDefault(vbdef1, ""));
                        String vbdef5 = bodydata.getOrDefault("vbdef5", "") + "";// 合同销售订单号
                        defList.clear();
                        defList = getDefList("BIP-ddh");
                        newBvo.setVbdef5(defList.getOrDefault(vbdef5, ""));
                        newBvo.setVbdef10(bodydata.getOrDefault("vbdef10", "") + "");// 项目名称
                        newBvo.setVbdef13(bodydata.getOrDefault("vbdef13", "") + "");// 国网行项目号
                        newBvo.setVbdef22(bodydata.getOrDefault("vbdef22", "") + "");// 国内采购订单号

                        bvoList.add(newBvo);
                    }
                }

                SaleOrderBVO[] array = bvoList.toArray(new SaleOrderBVO[0]);
                vo.setChildrenVO(array);
            }

            // 填充默认值
            new SaleOrderSaveFillValue().setDefValue1(copyVOs);
            Map<String, List<SaleOrderBVO>> listMap = new HashMap<>();
            for (SaleOrderVO copyVO : copyVOs) {
                List<SaleOrderBVO> newBvoList = new ArrayList<>();
                for (SaleOrderBVO saleOrderBVO : copyVO.getChildrenVO()) {
                    if (VOStatus.NEW == saleOrderBVO.getStatus()) {
                        SaleOrderBVO newBvo = (SaleOrderBVO) saleOrderBVO.clone();
                        newBvoList.add(newBvo);
                    }
                }
                listMap.put(copyVO.getParentVO().getCsaleorderid(), newBvoList);
            }
            if (!listMap.isEmpty()) {
                for (SaleOrderVO oldVO : oldVOs) {
                    String csaleorderid = oldVO.getParentVO().getCsaleorderid();
                    SaleOrderBVO oneBvo = oldVO.getChildrenVO()[0];
                    // 折本汇率
                    UFDouble nexchangerate = oneBvo.getNexchangerate();
                    nexchangerate = getUFDouble_NullAsOne(nexchangerate);
                    List<SaleOrderBVO> newBvoList = listMap.get(csaleorderid);
                    if (newBvoList != null && !newBvoList.isEmpty()) {
                        // 上边填充默认值的时候取了系统的默认汇率，需要用BIP传的
                        for (SaleOrderBVO saleOrderBVO : newBvoList) {
                            saleOrderBVO.setNexchangerate(nexchangerate);
                        }
                        SaleOrderBVO[] bvos = oldVO.getChildrenVO();
                        List<SaleOrderBVO> bvoList = new ArrayList<>(Arrays.asList(bvos));
                        // 添加新增行
                        bvoList.addAll(newBvoList);
                        SaleOrderBVO[] array = bvoList.toArray(new SaleOrderBVO[0]);
                        oldVO.setChildrenVO(array);
                    }

                }
            }
            /*
             * for (SaleOrderVO combinBillVO : copyVOs) { for (SaleOrderBVO saleOrderBVO :
             * combinBillVO.getChildrenVO()) { // 将实体对象转换为JSON字符串 String jsonString =
             * JSON.toJSONString(saleOrderBVO); NCCForUAPLogger.debug("jsonString:" +
             * jsonString); } }
             */

        } catch (Exception e) {
            Logger.error("APISaleOrderMaitainImpl-addBvo:" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private UFDouble getUFDouble_NullAsOne(Object value) {
        if ((value == null) || (value.toString().trim().equals("")) || (value.toString().trim().equals("~")))
            return UFDouble.ONE_DBL;
        if ((value instanceof UFDouble))
            return (UFDouble) value;
        if ((value instanceof BigDecimal)) {
            return new UFDouble((BigDecimal) value);
        }
        return new UFDouble(value.toString().trim());
    }

    /**
     * 回写BIP旗舰版的合同销售订单
     *
     * @author mzr
     * @date 2025/5/23
     */
    @Override
    public void updateBipFlagSo(Map<String, Object> paramMap) throws Exception {
        String csaleorderbid = (String) paramMap.get("csaleorderbid");
        Map<String, Object> soMap = getSaleOrderInfo(csaleorderbid);
        if (soMap == null) {
            return;
        }
        // 修改销售订单表 vdef8 MES工艺路线
        if (paramMap.containsKey("vdef8")) {
            String orderSql = "update so_saleorder set vdef8 = '[vdef8]' where csaleorderid = '[csaleorderid]'";
            orderSql = orderSql.replace("[vdef8]", paramMap.getOrDefault("vdef8", "") + "");
            orderSql = orderSql.replace("[csaleorderid]", soMap.getOrDefault("csaleorderid", "") + "");
            int num1 = getDao().executeUpdate(orderSql);
            NCCForUAPLogger.debug("updateDef-num1:" + num1);
        }
        // 如果不包含BOM配置完成时间、工艺配置完成时间，则不同步
        if (!paramMap.containsKey("vbdef16") && !paramMap.containsKey("vbdef17")) {
            return;
        }
        // 如果没有存合同销售订单信息则不回写
        if (soMap.get("vbdef11") == null || soMap.get("vdef9") == null) {
            return;
        }
        Map<String, String> bipParamMap = checkBipParam();
        if (bipParamMap.isEmpty()) {
            return;
        }
        String baseUrl = bipParamMap.get("baseUrl");
        String soUpdateUrl = bipParamMap.get("contractSaleOrder");
        if (StringUtils.isEmpty(soUpdateUrl)) {
            return;
        }
        String accessToken = getAccessToken(baseUrl, bipParamMap);
        Map<String, String> tokenParam = new HashMap<>();
        tokenParam.put("access_token", accessToken);
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        String updateUrl = baseUrl + soUpdateUrl;
        JSONObject bodyJson = new JSONObject();
        JSONObject updateJson = new JSONObject();
        List<Map<String, Object>> l_map_f = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        // bomConfigureFinishDate BOM配置完成日期
        String vbdef16 = convertDateString(paramMap.get("vbdef16") + "");
        map.put("bomConfigureFinishDate", vbdef16);
        // craftConfigureFinishDate 工艺配置完成日期
        String vbdef17 = convertDateString(paramMap.get("vbdef17") + "");
        map.put("craftConfigureFinishDate", vbdef17);
        // BIP合同销售订单更新 子表id
        map.put("id", soMap.get("vbdef11"));
        l_map_f.add(map);
        updateJson.put("contractOrdersList", l_map_f);
        // BIP合同销售订单更新 主表id
        updateJson.put("id", soMap.get("vdef9"));
        bodyJson.put("HTXSDD", updateJson);
        NCCForUAPLogger.debug("updateBipFlagSo-bodyJson:" + bodyJson);
        Logger.error("updateBipFlagSo-bodyJson:" + bodyJson);
        String resultString = doSendHttp(updateUrl, "POST", tokenParam, "", headers, bodyJson.toJSONString());
        NCCForUAPLogger.debug("updateBipFlagSo-resultString:" + resultString);
        Logger.error("updateBipFlagSo-resultString:" + resultString);
    }

    private Map<String, Object> getSaleOrderInfo(String csaleorderbid) throws BusinessException {
        IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String sql = " select s.vdef9,s.csaleorderid," +
                " sb.csaleorderbid,sb.vbdef11" +
                " from so_saleorder_b sb" +
                " inner join so_saleorder s on sb.csaleorderid=s.csaleorderid" +
                " where sb.csaleorderbid='" + csaleorderbid + "' ";
        return (Map<String, Object>) queryBS.executeQuery(sql, new MapProcessor());
    }

    private Map<String, String> checkBipParam() {
        Map<String, String> map = new HashMap<String, String>();
        String strWhere = " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='BIP-sq' and dr=0 )  and dr=0";
        try {
            DefdocVO[] defdocVOs = (DefdocVO[]) new HYSuperDMO().queryByWhereClause(DefdocVO.class, strWhere);
            if (defdocVOs != null && defdocVOs.length > 0) {
                for (DefdocVO defdocVO : defdocVOs) {
                    map.put(defdocVO.getCode().trim(), defdocVO.getName());
                }
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return map;

    }

    private String getAccessToken(String baseUrl, Map<String, String> bipParamMap) throws Exception {
        String tokenUrl = baseUrl + "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken";
//		String appKey = "f10c4bf17b1d4e1fb08eb82bf8540eab";
        String appKey = bipParamMap.get("appKey");

//		String appSecret = "71dc2a58ca378c1a1143231a62e73e75a60e9236";
        String appSecret = bipParamMap.get("appSecret");
        String accessToken = "";
        Map<String, String> params = new HashMap<>();


        params.put("appKey", appKey);
        String timestamp = String.valueOf(System.currentTimeMillis());
        params.put("timestamp", timestamp);
        // 计算签名
        Map<String, String> treeMap;
        if (params instanceof TreeMap) {
            treeMap = params;
        } else {
            treeMap = new TreeMap<>(params);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }
        Mac mac = Mac.getInstance("HmacSHA256");

        mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = Base64.getEncoder().encodeToString(signData);
        String signature = URLEncoder.encode(base64String, "UTF-8");
        params.put("signature", signature);

        String responseString = doGet(tokenUrl, params);

        Gson gson = new Gson();
        Map result = gson.fromJson(responseString, Map.class);
        if (com.yonyou.cloud.utils.StringUtils.equals("00000", result.get("code").toString())) {
            Map<String, Object> tokenInfo = (Map<String, Object>) result.get("data");
            accessToken = (String) tokenInfo.get("access_token");

        }
        return accessToken;
    }

    public static String doSendHttp(String baseUrl, String method, Map<String, String> paramMap, String mediaType, Map<String, String> headers, String json) {
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(baseUrl);
            if (paramMap != null) {
                sb.append("?");
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key).append("=").append(value).append("&");
                    baseUrl = sb.substring(0, sb.toString().length() - 1);
                }
            }
            URL urlobj = new URL(baseUrl);
            if ("https".equalsIgnoreCase(urlobj.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            urlConnection = (HttpURLConnection) urlobj.openConnection();
            urlConnection.setConnectTimeout(50000);
            urlConnection.setRequestMethod(method);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            // 如果设置了自定义头，则打印它们
            if (headers != null && !headers.isEmpty()) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    urlConnection.addRequestProperty(entry.getKey(), entry.getValue());
//                    log.error("Request Header: " + entry.getKey() + ": " + entry.getValue());
                }
            }
            if (json != null && !json.isEmpty()) {
//                log.error("Request Body: " + json);
                urlConnection.setDoInput(true);
                urlConnection.setDoOutput(true);
                out = urlConnection.getOutputStream();
                out.write(json.getBytes(StandardCharsets.UTF_8));
                out.flush();
            }
            int resCode = urlConnection.getResponseCode();
            String ecod = urlConnection.getContentEncoding();
            if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED
                    || resCode == HttpURLConnection.HTTP_ACCEPTED) {
                if (com.yonyou.cloud.utils.StringUtils.isNotEmpty(ecod) && ecod.equals("gzip")) {
                    in = new GZIPInputStream(urlConnection.getInputStream());
                } else {
                    in = urlConnection.getInputStream();
                }
            } else {
                in = urlConnection.getErrorStream();
            }
            bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            StringBuilder temp = new StringBuilder();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            if (ecod == null || ecod.equals("gzip")) {
                ecod = StandardCharsets.UTF_8.name();
            }
            result = new String(temp.toString().getBytes(StandardCharsets.UTF_8), ecod);
        } catch (Exception e) {
            JSONObject js = new JSONObject();
            js.put("", -1);
            js.put("message", "调用外系统接口失败：" + e.getMessage());
            result = js.toString();
            e.printStackTrace();
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            urlConnection.disconnect();
        }
        return result;
    }

    private static String doGet(String path, Map<String, String> params) throws Exception {
        HttpURLConnection conn = null;
        InputStream is = null;
        BufferedReader br = null;
        StringBuilder result = new StringBuilder();
        try {
            if (params != null) {
                String paramStr = "";
                for (String key : params.keySet()) {
                    if (!paramStr.isEmpty()) {
                        paramStr += '&';
                    }
                    paramStr += key + '=' + params.get(key);
                }

                if (path.indexOf('?') > 0) {
                    path += '&' + paramStr;
                } else {
                    path += '?' + paramStr;
                }
            }
            // 创建远程url连接对象
            URL url = new URL(path);
            if ("https".equalsIgnoreCase(url.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            // 通过远程url连接对象打开一个连接，强转成HTTPURLConnection类
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            // 设置连接超时时间和读取超时时间
            conn.setConnectTimeout(120000);
            conn.setReadTimeout(120000);
            conn.setRequestProperty("Accept", "application/json");
            // 发送请求
            conn.connect();
            // 通过conn取得输入流，并使用Reader读取
            if (200 == conn.getResponseCode()) {
                is = conn.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String line;
                while ((line = br.readLine()) != null) {
                    result.append(line);
                    System.out.println(line);
                }
            } else {
                System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    /**
     * 转换日期字符串
     * yyyy-MM-dd HH:mm:ss to yyyy-MM-dd
     *
     * @param input 输入
     * @return {@link String}
     */
    public String convertDateString(String input) throws BusinessException {
        if (com.yonyou.cloud.utils.StringUtils.isEmpty(input) || "null".equals(input)) {
            return input;
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = formatter.parse(input);
            LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            return localDate.format(dtf);
        } catch (ParseException e) {
            throw new BusinessException("Invalid date format", e);
        }
    }

    private void updatePmoBill(SaleOrderVO[] vos) {
        // 同步修改流程生产订单的国网行项目号、国内采购订单号
        for (SaleOrderVO vo : vos) {
            SaleOrderBVO[] bvos = vo.getChildrenVO();
            for (SaleOrderBVO bvo : bvos) {
                String csaleorderbid = bvo.getCsaleorderbid();
                // 源头单据明细ID（vfirstbid）
                if (csaleorderbid == null || csaleorderbid.isEmpty()) {
                    continue; // 跳过无效数据
                }

                // 从销售订单明细中获取需要更新的字段
                String vbdef13 = bvo.getVbdef13(); // vbdef13 国网行项目号
                String vbdef22 = bvo.getVbdef22(); // vbdef22 国内采购订单号
                if (StringUtils.isEmpty(vbdef13) && StringUtils.isEmpty(vbdef22)) {
                    continue;
                }

                // 构建并执行更新SQL
                String updateSql = "UPDATE mm_mo SET vdef8 = '[vdef8]', vdef14 = '[vdef14]' WHERE vfirstbid = '[bid]'";
                updateSql = updateSql.replace("[vdef8]", vbdef13);
                updateSql = updateSql.replace("[vdef14]", vbdef22);
                updateSql = updateSql.replace("[bid]", csaleorderbid);
                try {
                    getDao().executeUpdate(updateSql);
                } catch (Exception e) {
                    ExceptionUtils.wrappBusinessException("so-updatePmoBill-exp: " + e.getMessage());
                }
            }
        }
    }

}
