package com.hzya.frame.plugin.lets.plugin.sales;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.base.PluginBaseEntity;
import com.hzya.frame.beanutil.BeanUtil;
import com.hzya.frame.plugin.lets.constant.OverallConstant;
import com.hzya.frame.plugin.lets.constant.ProfilesActiveConstant;
import com.hzya.frame.plugin.lets.entity.*;
import com.hzya.frame.plugin.lets.ofs.dao.ITocofsSaleoutDao;
import com.hzya.frame.plugin.lets.ofs.dao.ITocofsSaleoutDetailedDao;
import com.hzya.frame.plugin.lets.ofs.entity.TocofsSaleoutDetailedEntity;
import com.hzya.frame.plugin.lets.ofs.entity.TocofsSaleoutEntity;
import com.hzya.frame.plugin.lets.ofs.service.ITocofsSaleoutService;
import com.hzya.frame.plugin.lets.ofsvo.QueryOfsSoSaleOutVo;
import com.hzya.frame.plugin.lets.queryvo.StartAndEndVo;
import com.hzya.frame.plugin.lets.resultvo.CacheTocMapVo;
import com.hzya.frame.plugin.lets.resultvo.CalculateDateVo;
import com.hzya.frame.plugin.lets.u8cdto.*;
import com.hzya.frame.plugin.lets.util.*;
import com.hzya.frame.split.SplitListByCountUtil;
import com.hzya.frame.ttxofs.dto.InterfaceParamDto;
import com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto;
import com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto;
import com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto;
import com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.SaleOutReturnMessageDto;
import com.hzya.frame.ttxofs.dto.ofssalesordersearch.SaleOrderMessageDto;
import com.hzya.frame.ttxofs.dto.stock.StockinOrderSearchResponse;
import com.hzya.frame.ttxofs.service.OfsUnifiedService;
import com.hzya.frame.u8c.ax.entity.Ass;
import com.hzya.frame.web.entity.JsonResultEntity;
import com.hzya.frame.web.exception.BaseSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * OFS销售出库单(TOC)生成U8C销售订单
 *
 * @author makejava
 * @since 2023-08-16 15:49:55
 */
public class SoSaleOutPluginInitializerToC extends PluginBaseEntity {

    Logger logger = LoggerFactory.getLogger(SoSaleOutPluginInitializerToC.class);

    private static final ReentrantLock LOCK = new ReentrantLock(true);

    private static final String PROD_FILED = "prod";
//
//    @Autowired
//    private SoSaleOutPluginInitializerToC soSaleOutPluginInitializerToC;

    @Override
    public void initialize() {
        logger.info(getPluginLabel() + "執行初始化方法initialize()");
    }

    @Override
    public void destroy() {
        logger.info(getPluginLabel() + "執行銷毀方法destroy()");
    }

    @Override
    public String getPluginId() {
        return "sales.SoSaleOutPluginInitializerToC";
    }

    @Override
    public String getPluginName() {
        return "OFS销售出库单(TOC)生成U8C销售订单";
    }

    @Override
    public String getPluginLabel() {
        return "OFS销售出库单(TOC)生成U8C销售订单";
    }

    @Override
    public String getPluginType() {
        return "3";
    }

    private static final String STOCK = "stock";

    private static final String TRAN = "tran";

    @Override
    public JsonResultEntity executeBusiness(JSONObject requestJson) throws Exception {
        long startMillis = System.currentTimeMillis();
        logger.info("executeBusiness方法调用开始：" + getPluginName() + "-插件");

//        if (ProfilesActiveConstant.TYPE_DETAIL_ERROR.equals(requestJson.get("type"))) {
//            throw new BaseSystemException("TOC退货业务，无法按单行推送！需要根据天的维度推送");
//        }

        try {
            String param = String.valueOf(requestJson.get("param"));
            String sceneType = String.valueOf(requestJson.get("sceneType"));//sceneType：stock、tran
            if (ProfilesActiveConstant.TYPE_VBILLCODE.equals(requestJson.get("type"))) {
                //按单号
                if (param != null && !"".equals(param)) {
                    startImplementStockByCode(param, sceneType);
                }
            } else if (ProfilesActiveConstant.TYPE_TIME_FRAME.equals(requestJson.get("type"))) {
                //前台页面功能日期推送，或者接口调用也行
                String craeteDateStr = computingTime(param);
                if (craeteDateStr != null && !"".equals(craeteDateStr)) {
                    splitDateAndPush(craeteDateStr, sceneType);
                }
            } else {
                if (ProfilesActiveConstant.LETS_PROFILES_ACTIVE.equals(PROD_FILED)) {
                    //默认被定时器执行，每天晚上凌晨0点5分
                    //暂定先同步TOC销售库存、再推送TOC销售确认收入
                    List<StartAndEndVo> startAndEndVos = calculateCalculateEntireDayPeriod(null);
                    startImplementStockByTime(startAndEndVos.get(0).getStart_time(), startAndEndVos.get(0).getEnd_time());
                    startImplementTranByTime(startAndEndVos.get(0).getStart_time(), startAndEndVos.get(0).getEnd_time());
                }
            }
        } catch (Exception e) {
            logger.error("executeBusiness方法异常", e);
        }
        long endMillis = System.currentTimeMillis();
        logger.info("executeBusiness方法调用结束：" + getPluginName() + "-插件 执行耗时：{}", (endMillis - startMillis));
        return null;
    }

    @Autowired
    private OfsUnifiedService ofsUnifiedService;

    @Autowired
    private TocOrderBasicArchivesCacheUtil basicArchivesCacheUtil;

    @Autowired
    private ITocofsSaleoutDao iTocofsSaleoutDao;

    @Autowired
    private ITocofsSaleoutDetailedDao iTocofsSaleoutDetailedDao;

    @Autowired
    private QueryBdBusitypeUtil queryBdBusitypeUtil;

    private static final String NOTHING = "无";

    private static final String ADD = "@0216@";

    @Autowired
    private ShopTobOrToCUtil shopTobOrToCUtil;

    @Autowired
    private OfsStandardUtil ofsStandardUtil;

    @Autowired
    private RdclUtil rdclUtil;

    /**
     * 库存同步，按指定时间拉取
     *
     * @param startTime O出库开始时间
     * @param endTime   O出库结束时间
     * @author liuyang
     */
    public void startImplementStockByTime(String startTime, String endTime) {
        long startMillis = System.currentTimeMillis();
        String threadNameStrStart = StrUtil.format("开始 OFS销售出库(TOC)同步U8C销售订单 开始 开始时间：{} 结束时间：{}", startTime, endTime);
        logger.info(threadNameStrStart);

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                LOCK.lock();
                try {
                    Assert.notNull(startTime, "查询条件，开始时间不能为空！");
                    Assert.notNull(endTime, "查询条件，结束时间不能为空！");

//                    CalculateDateVo calculateDateVo = DateStrUtil.calculateCalculateEntireDayPeriod(dateStr);
                    String tobShop = shopTobOrToCUtil.getCommaShop("TOC");

                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList = new ArrayList<>();
                    QueryOfsSoSaleOutVo queryOfsSoSaleOutVo = new QueryOfsSoSaleOutVo();
//                    queryOfsSoSaleOutVo.setShipAt_start(calculateDateVo.getStart_time());
//                    queryOfsSoSaleOutVo.setShipAt_end(calculateDateVo.getEnd_time());
                    queryOfsSoSaleOutVo.setShipAt_start(startTime);
                    queryOfsSoSaleOutVo.setShipAt_end(endTime);
                    queryOfsSoSaleOutVo.setClientCode("LETS");
                    queryOfsSoSaleOutVo.setInternalInstructionType("SALES");
                    queryOfsSoSaleOutVo.setStatus(900L);
                    queryOfsSoSaleOutVo.setPageNo(1L);
                    queryOfsSoSaleOutVo.setPageSize(100L);
                    queryOfsSoSaleOutVo.setStoreCode(tobShop);
//                    queryOfsSoSaleOutVo.setCode("LETS-SH2024070500000003");
                    ofsStandardUtil.queryOfsSaleOrder(queryOfsSoSaleOutVo, headerDetailsDtoList, 1L, "ofs.shipment.search");
                    logger.info("数据返回行数：{}", headerDetailsDtoList.size());
                    if (headerDetailsDtoList.size() > 0) {
                        getSetStock(headerDetailsDtoList);
                    } else {
                        logger.info("TOC没有查询到任何数据！不需要同步");
                    }
                } catch (Exception e) {
                    logger.error("startImplement方法抛出异常", e);
                } finally {
//                    try {
//                        basicArchivesCacheUtil.clearCache();
//                    } catch (Exception e) {
//                        logger.info("清理档案缓存失败", e);
//                    }
                    LOCK.unlock();
                }
            }
        }, threadNameStrStart);
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("thread.join()异常", e);
        }
        long endMillis = System.currentTimeMillis();
        String threadNameStrEnd = StrUtil.format("结束 OFS销售出库(TOC)同步U8C销售订单 结束 开始时间：{} 结束时间：{} 耗时：{}", startTime, endTime, (endMillis - startMillis));
        logger.info(threadNameStrEnd);
    }

    /**
     * 根据出库单编码拉取
     *
     * @param code O销售出库单编码
     * @author liuyang
     */
    public void startImplementStockByCode(String code, String sceneType) {
        long startMillis = System.currentTimeMillis();
        String threadNameStrStart = StrUtil.format("OFS销售出库(TOC)同步U8C销售订单 开始 出库单单据号：{}", code);
        logger.info(threadNameStrStart);

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                LOCK.lock();
                try {
                    Assert.notNull(code, "O出库单编码不能为空！code is null！");
                    Assert.notNull(sceneType, "场景类型不能为空！");

                    String tobShop = shopTobOrToCUtil.getCommaShop("TOC");
                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList = new ArrayList<>();
                    QueryOfsSoSaleOutVo queryOfsSoSaleOutVo = new QueryOfsSoSaleOutVo();
                    queryOfsSoSaleOutVo.setClientCode("LETS");
                    queryOfsSoSaleOutVo.setInternalInstructionType("SALES");
                    queryOfsSoSaleOutVo.setStatus(900L);
                    queryOfsSoSaleOutVo.setPageNo(1L);
                    queryOfsSoSaleOutVo.setPageSize(100L);
                    queryOfsSoSaleOutVo.setStoreCode(tobShop);
                    queryOfsSoSaleOutVo.setCode(code);
                    ofsStandardUtil.queryOfsSaleOrder(queryOfsSoSaleOutVo, headerDetailsDtoList, 1L, "ofs.shipment.search");
                    logger.info("数据返回行数：{}", headerDetailsDtoList.size());
                    if (headerDetailsDtoList.size() > 0) {
                        if (sceneType.equals("stock")) {
                            getSetStock(headerDetailsDtoList);
                        } else if (sceneType.equals("tran")) {
                            getSetTran(headerDetailsDtoList);
                        }
                    } else {
                        logger.info("没有查询到任何数据！不需要同步");
                    }
                } catch (Exception e) {
                    logger.error("startImplement方法抛出异常", e);
                } finally {
//                    try {
//                        basicArchivesCacheUtil.clearCache();
//                    } catch (Exception e) {
//                        logger.info("清理档案缓存失败", e);
//                    }
                    LOCK.unlock();
                }
            }
        }, threadNameStrStart);
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("thread.join()异常", e);
        }
        long endMillis = System.currentTimeMillis();
        String threadNameStrEnd = StrUtil.format("OFS销售出库(TOC)同步U8C销售订单 结束 出库单单据号：{} 耗时：{}", code, (endMillis - startMillis));
        logger.info(threadNameStrEnd);
    }

    /**
     * 按交易完成时间拉取生成
     *
     * @param startTime O交易完成开始时间
     * @param endTime   O交易完成结束时间
     * @author liuyang
     */
    public void startImplementTranByTime(String startTime, String endTime) {
        long startMillis = System.currentTimeMillis();
        String threadNameStrStart = StrUtil.format("开始OFS销售出库(TOC)同步U8C销售订单 开始时间：{} 结束时间：{}", startTime, endTime);
        logger.info(threadNameStrStart);

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                LOCK.lock();
                try {
                    Assert.notNull(startTime, "查询条件，开始时间不能为空！");
                    Assert.notNull(endTime, "查询条件，结束时间不能为空！");

//                    CalculateDateVo calculateDateVo = DateStrUtil.calculateCalculateEntireDayPeriod(dateStr);
                    String tocShop = shopTobOrToCUtil.getCommaShop("TOC");

                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList = new ArrayList<>();
                    QueryOfsSoSaleOutVo queryOfsSoSaleOutVo = new QueryOfsSoSaleOutVo();
//                    queryOfsSoSaleOutVo.setShipAt_start(calculateDateVo.getStart_time());
//                    queryOfsSoSaleOutVo.setShipAt_end(calculateDateVo.getEnd_time());
                    queryOfsSoSaleOutVo.setTradeSuccessAt_start(startTime);
                    queryOfsSoSaleOutVo.setTradeSuccessAt_end(endTime);
                    queryOfsSoSaleOutVo.setClientCode("LETS");
                    queryOfsSoSaleOutVo.setInternalInstructionType("SALES");
                    queryOfsSoSaleOutVo.setSourceOrderStatus("TRADE_FINISHED");//交易成功状态
//                    queryOfsSoSaleOutVo.setStatus(900L);
                    queryOfsSoSaleOutVo.setPageNo(1L);
                    queryOfsSoSaleOutVo.setPageSize(100L);
                    queryOfsSoSaleOutVo.setStoreCode(tocShop);
//                    queryOfsSoSaleOutVo.setCode("LETS-SH2024070500000003");
                    ofsStandardUtil.queryOfsSaleOrder(queryOfsSoSaleOutVo, headerDetailsDtoList, 1L, "ofs.shipment.search");
                    logger.info("TOC数据返回行数：{}", headerDetailsDtoList.size());
                    if (headerDetailsDtoList.size() > 0) {
                        getSetTran(headerDetailsDtoList);
                    } else {
                        logger.info("TOC没有查询到任何数据！不需要同步");
                    }
                } catch (Exception e) {
                    logger.error("startImplement方法抛出异常", e);
                } finally {
//                    try {
//                        basicArchivesCacheUtil.clearCache();
//                    } catch (Exception e) {
//                        logger.info("清理档案缓存失败", e);
//                    }
                    LOCK.unlock();
                }
            }
        }, threadNameStrStart);
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("thread.join()异常", e);
        }
        long endMillis = System.currentTimeMillis();
        String threadNameStrEnd = StrUtil.format("结束OFS销售出库(TOC)同步U8C销售订单 开始时间：{} 结束时间：{} 耗时：{}", startTime, endTime, (endMillis - startMillis));
        logger.info(threadNameStrEnd);
    }

    /**
     * 库存同步：触发数据转换之前的预备逻辑
     *
     * @author liuyang
     */
    private void getSetStock(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        //保存到mysql底表
        batchInsert(headerDetailsDtoList);
        //过滤成功的数据
        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtos = filterDataStock(headerDetailsDtoList);
        //执行推送主逻辑
        implementStock(headerDetailsDtos);
    }

    /**
     * 交易成功：触发数据转换之前的预备逻辑
     *
     * @author liuyang
     */
    private void getSetTran(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        //保存到mysql底表
        batchInsert(headerDetailsDtoList);
        //过滤成功的数据
        //headerDetailsDtos携带红、蓝单据推送成功与否的明细行
        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtos = filterDataTran(headerDetailsDtoList);
        //执行推送采购主逻辑
        implementTran(headerDetailsDtos);
    }

    /**
     * 出库成功：过滤掉成功的数据
     *
     * @author liuyang
     */
    private List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> filterDataStock(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
//        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList1 = new ArrayList<>();
        List<TocofsSaleoutDetailedEntity> allTocofsSaleoutDetailedEntityList = new ArrayList<>();
        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            List<List<HeaderDetailsDto>> splitListByCount = SplitListByCountUtil.splitListByCount(headerDetailsDtoList, 100);
            for (int i = 0; i < splitListByCount.size(); i++) {
                List<HeaderDetailsDto> headerDetailsDtoList2 = splitListByCount.get(i);
                String idStr = commaConcatenatedPrimaryKeyStock(headerDetailsDtoList2);
                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = queryStockTocOutLog(idStr);
                allTocofsSaleoutDetailedEntityList.addAll(tocofsSaleoutDetailedEntityList);
            }
        }
        return filterDataRowsAsPushOrFailedStock(allTocofsSaleoutDetailedEntityList, headerDetailsDtoList);
    }

    /**
     * 交易成功业务：过滤掉成功的数据
     *
     * @author liuyang
     */
    private List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> filterDataTran(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        List<TocofsSaleoutDetailedEntity> allTocofsSaleoutDetailedEntityList = new ArrayList<>();
        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            List<List<HeaderDetailsDto>> splitListByCount = SplitListByCountUtil.splitListByCount(headerDetailsDtoList, 100);
            for (int i = 0; i < splitListByCount.size(); i++) {
                List<HeaderDetailsDto> headerDetailsDtoList2 = splitListByCount.get(i);
                String idStr = commaConcatenatedPrimaryKeyStock(headerDetailsDtoList2);
                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = queryStockTocOutLog(idStr);
                allTocofsSaleoutDetailedEntityList.addAll(tocofsSaleoutDetailedEntityList);
            }
        }
        return filterDataRowsAsPushOrFailedTran(allTocofsSaleoutDetailedEntityList, headerDetailsDtoList);
    }

    /**
     * 逗号拼接字符串主键，作为批处理的一部分，方便下一步的批量查询操作
     *
     * @author liuyang
     */
    private String commaConcatenatedPrimaryKeyStock(List<HeaderDetailsDto> headerDetailsDtoList2) throws Exception {
        StringBuffer idStr = new StringBuffer();
        if (headerDetailsDtoList2 != null && headerDetailsDtoList2.size() > 0) {
            for (int i = 0; i < headerDetailsDtoList2.size(); i++) {
                HeaderDetailsDto headerDetailsDto = headerDetailsDtoList2.get(i);
                HeaderDto header = headerDetailsDto.getHeader();
                List<DetailsDto> details = headerDetailsDto.getDetails();
                for (int j = 0; j < details.size(); j++) {
                    DetailsDto detailsDto = details.get(j);
                    Assert.notNull(detailsDto.getId(), "O明细主键不能为空！");
                    Assert.state(!"".equals(detailsDto.getId()), "O明细主键不能为空！");
                    idStr.append(detailsDto.getId());
                    idStr.append(",");
                }
            }
        }
        if (idStr.length() > 0) {
            return idStr.substring(0, idStr.length() - 1);
        }
        return null;
    }

    /**
     * 批查询toc出库日志，查询的量由splitListByCount方法控制
     *
     * @author liuyang
     */
    private List<TocofsSaleoutDetailedEntity> queryStockTocOutLog(String idStr) throws Exception {
        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = null;
        if (idStr != null && !"".equals(idStr.trim())) {
            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
            tocofsSaleoutDetailedEntity.setIds(idStr);
            tocofsSaleoutDetailedEntityList = iTocofsSaleoutDetailedDao.query(tocofsSaleoutDetailedEntity);
        } else {
            logger.error("idStr为空，无法查询数据！");
        }
        return tocofsSaleoutDetailedEntityList;
    }

    /**
     * 筛选出未推送、或者失败的数据行
     *
     * @param allTocofsSaleoutDetailedEntityList 日志行状态
     * @param headerDetailsDtoList               返回结果
     * @author liuyang
     */
    private List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> filterDataRowsAsPushOrFailedStock(List<TocofsSaleoutDetailedEntity> allTocofsSaleoutDetailedEntityList, List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> targetHeaderDetailsDtoList = new ArrayList<>();
        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            //字段Y(成功)或者为H(待处理)可以视为成功，完成了小段业务闭环的数据行
            String succeseeY = "Y";
            String succeseeH = "H";
            for (int i = 0; i < headerDetailsDtoList.size(); i++) {
                HeaderDetailsDto headerDetailsDto = headerDetailsDtoList.get(i);
                HeaderDto header = headerDetailsDto.getHeader();
                List<DetailsDto> details = headerDetailsDto.getDetails();

                List<DetailsDto> targetDetails = new ArrayList<>();
                for (int j = 0; j < details.size(); j++) {
                    DetailsDto detailsDto = details.get(j);
                    Boolean isSuccess = false;
                    String newstate = null;
                    if (allTocofsSaleoutDetailedEntityList.size() > 0) {
                        for (int k = 0; k < allTocofsSaleoutDetailedEntityList.size(); k++) {
                            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = allTocofsSaleoutDetailedEntityList.get(k);
                            if (tocofsSaleoutDetailedEntity.getId().equals(detailsDto.getId())) {
                                newstate = tocofsSaleoutDetailedEntity.getNewstate();
                                if (succeseeY.equals(newstate) || succeseeH.equals(newstate)) {
                                    isSuccess = true;
                                }
                            }
                        }
                    }
                    if (!isSuccess) {
                        detailsDto.setNewState(newstate);
                        targetDetails.add(detailsDto);
                    }
                }
                if (targetDetails.size() > 0) {
                    //如果明细行中，还存在未推送或者失败的数据，则需要更新明细行
                    headerDetailsDto.setDetails(targetDetails);
                    targetHeaderDetailsDtoList.add(headerDetailsDto);
                }
            }
        }
        return targetHeaderDetailsDtoList;
    }

    /**
     * 筛选出未推送、或者失败的数据行
     *
     * @param allTocofsSaleoutDetailedEntityList 日志行状态
     * @param headerDetailsDtoList               返回结果
     * @author liuyang
     */
    private List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> filterDataRowsAsPushOrFailedTran(List<TocofsSaleoutDetailedEntity> allTocofsSaleoutDetailedEntityList, List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> targetHeaderDetailsDtoList = new ArrayList<>();
        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            //字段Y(成功)或者为H(待处理)可以视为成功，完成了小段业务闭环的数据行
            String succeseeY = "Y";
            String succeseeH = "H";
            for (int i = 0; i < headerDetailsDtoList.size(); i++) {
                HeaderDetailsDto headerDetailsDto = headerDetailsDtoList.get(i);
                HeaderDto header = headerDetailsDto.getHeader();
                List<DetailsDto> details = headerDetailsDto.getDetails();

                List<DetailsDto> targetDetails = new ArrayList<>();
                for (int j = 0; j < details.size(); j++) {
                    DetailsDto detailsDto = details.get(j);

                    Boolean isSuccess = false;
                    String newstate2 = null;
                    String newstate3 = null;
//                    TocofsSaleoutDetailedEntity targetTocofsSaleoutDetailedEntity = null;
                    if (allTocofsSaleoutDetailedEntityList != null && allTocofsSaleoutDetailedEntityList.size() > 0) {
                        for (int k = 0; k < allTocofsSaleoutDetailedEntityList.size(); k++) {
                            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = allTocofsSaleoutDetailedEntityList.get(k);
                            if (tocofsSaleoutDetailedEntity.getId().equals(detailsDto.getId())) {
                                newstate2 = tocofsSaleoutDetailedEntity.getNewstate2();
                                newstate3 = tocofsSaleoutDetailedEntity.getNewstate3();
//                            targetTocofsSaleoutDetailedEntity = tocofsSaleoutDetailedEntity;
                                //验证交易成功(红)是否成功、(销售)交易成功(蓝)是否成功 两者如果都成功，则过滤掉，如果其中一个不能成功，则还是需要进行补推！
                                //验证红或蓝单据是否推送成功的代码，在implementTran中实现
                                if ((succeseeY.equals(newstate2) || succeseeH.equals(newstate2)) && (succeseeY.equals(newstate3) || succeseeH.equals(newstate3))) {
                                    isSuccess = true;
                                }
                            }
                        }
                    }
                    if (!isSuccess) {
                        //拷贝推送状态参数，方便推送是进行判断
                        detailsDto.setNewState2(newstate2);
                        detailsDto.setNewState3(newstate3);
                        targetDetails.add(detailsDto);
                    }
                }
                if (targetDetails.size() > 0) {
                    //如果明细行中，还存在未推送或者失败的数据，则需要更新明细行
                    headerDetailsDto.setDetails(targetDetails);
                    targetHeaderDetailsDtoList.add(headerDetailsDto);
                }
            }
        }
        return targetHeaderDetailsDtoList;
    }

    /**
     * 交易成功：过滤掉成功的数据
     *
     * @author liuyang
     */
//    private List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> filterDataSTran(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) {
//        List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList1 = new ArrayList<>();
//        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
//            //TODO 出库单明细主键，需要O返回，目前没有，已经提需求
//            headerDetailsDtoList1.addAll(headerDetailsDtoList);
//        }
//        return headerDetailsDtoList1;
//    }

    /**
     * 保存抓取到的数据到mysql底表，如果底表里已经存在，则会忽略
     *
     * @param headerDetailsDtoList 数据行
     */
    private void batchInsert(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        if (headerDetailsDtoList != null) {
            logger.error("需要保存或者更新到mysql底表的数量为:{}", headerDetailsDtoList.size());
        }
        // 测试对象字段更新
//        headerDetailsDtoList.get(0).getHeader().setClientCode("LETS2");
//        headerDetailsDtoList.get(0).getHeader().setInternalInstructionType("SALES22");
//        headerDetailsDtoList.get(0).getDetails().get(0).setSkuName("22222");
//        headerDetailsDtoList.get(0).getDetails().get(0).setIsGift("11111");
//        headerDetailsDtoList.get(0).getDetails().get(0).setQuantityUM("33333");
        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            try {
                List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto> headerDetailsDtoList1 = new ArrayList<>();
                List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto> headerDetailsDtoList2 = new ArrayList<>();

                for (com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto index : headerDetailsDtoList) {
                    com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto header = index.getHeader();// 主表
                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto> details = index.getDetails();//明细表
                    for (int i = 0; i < details.size(); i++) {
                        DetailsDto detailsDto = details.get(i);
                        detailsDto.setHeaderDto(header);
                    }
                    headerDetailsDtoList1.add(header);
                    headerDetailsDtoList2.addAll(details);
                }

                //每50作为一个批次插入主表，根据主键（id）判断是否重复，如果重复的，则不进行插入
                List<List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto>> ofssaleorderoutsearchList = SplitListByCountUtil.splitListByCount(headerDetailsDtoList1, 50);
                for (int i = 0; i < ofssaleorderoutsearchList.size(); i++) {
                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto> headerDtoList = ofssaleorderoutsearchList.get(i);
                    List<TocofsSaleoutEntity> tocofsSaleoutEntityList = copyHeaderDto(headerDtoList);
                    if (tocofsSaleoutEntityList != null && tocofsSaleoutEntityList.size() > 0) {
                        logger.info("TocofsSaleoutEntity：插入底表{}个对象（表头）", tocofsSaleoutEntityList.size());
                        iTocofsSaleoutDao.entityInsertOrUpdateBatch(tocofsSaleoutEntityList);
                    } else {
                        logger.info("TocofsSaleoutEntity：TOC业务没有对象被插入表头底表");
                    }
                }

                //插入明细表
                List<List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto>> detailsDtoList = SplitListByCountUtil.splitListByCount(headerDetailsDtoList2, 50);
                for (int i = 0; i < detailsDtoList.size(); i++) {
                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto> detailsDtos = detailsDtoList.get(i);
                    List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntities = copyDetailsDto(detailsDtos);
                    if (tocofsSaleoutDetailedEntities.size() > 0) {
                        logger.info("TocofsSaleoutDetailedEntity：插入底表{}个对象（表体）", tocofsSaleoutDetailedEntities.size());
                        iTocofsSaleoutDetailedDao.entityInsertOrUpdateBatch(tocofsSaleoutDetailedEntities);
                    } else {
                        logger.info("TocofsSaleoutDetailedEntity：没有对象被插入表头底表");
                    }
                }
            } catch (Exception e) {
                logger.error("TOC业务保存到Mysql底表失败！TocofsSaleoutEntity、TocofsSaleoutDetailedEntity保存失败", e);
            }
        }
    }

    /**
     * 查询OFS结果集
     *
     * @param queryOfsSoSaleOutVo  查询参数
     * @param headerDetailsDtoList 查询结果集
     * @param pageNo               从第pageNo页开始查询
     */
//    private void queryOfsSaleOrder(QueryOfsSoSaleOutVo queryOfsSoSaleOutVo, List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList, Long pageNo) throws Exception {
//
//        Long pageSize = 200L;
//        queryOfsSoSaleOutVo.setPageNo(pageNo);
//        queryOfsSoSaleOutVo.setPageSize(pageSize);
//
//        InterfaceParamDto interfaceParamDto = new InterfaceParamDto();
//        interfaceParamDto.setApi("ofs.shipment.search");
//        interfaceParamDto.setData(JSON.toJSONString(queryOfsSoSaleOutVo));
//        SaleOutReturnMessageDto saleOutReturnMessageDto = (SaleOutReturnMessageDto) ofsUnifiedService.unified(interfaceParamDto);
//        if (saleOutReturnMessageDto != null) {
//            if ("false".equals(saleOutReturnMessageDto.getError()) && "0".equals(saleOutReturnMessageDto.getCode()) && "Success".equals(saleOutReturnMessageDto.getMsg())) {
//                List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList1 = saleOutReturnMessageDto.getData();
//                if (headerDetailsDtoList1 != null && headerDetailsDtoList1.size() > 0) {
//                    headerDetailsDtoList.addAll(headerDetailsDtoList1);
//
//                    //TODO OFS没有提供分页字段
//                }
//            } else {
//                //2024年7月30日 13:47:04 查询失败
//                logger.error("查询失败，失败原因:{}", JSON.toJSON(saleOutReturnMessageDto));
//            }
//        } else {
//            logger.error("returnMessageBasics为空！queryOfsSoSaleOutVo对象结果：{}", JSON.toJSON(queryOfsSoSaleOutVo));
//        }
//    }

//    public void queryOfsSaleOrder() throws Exception {
//        QueryOfsSoSaleOutVo queryOfsSoSaleOutVo = new QueryOfsSoSaleOutVo();
//        queryOfsSoSaleOutVo.setCreated_start("2024-07-05 16:38:00");
//        queryOfsSoSaleOutVo.setCreated_end("2024-07-05 16:40:30");
//        queryOfsSoSaleOutVo.setClientCode("LETS");
////        queryOfsSoSaleOutVo.setInternalInstructionType("SALES");
//        queryOfsSoSaleOutVo.setCompanyCode("SHLZ");
////        queryOfsSoSaleOutVo.setStatus(900L);
//        queryOfsSoSaleOutVo.setPageNo(1L);
//        queryOfsSoSaleOutVo.setPageSize(50L);
//        queryOfsSoSaleOutVo.setCode("LETS-SH2024070500000003");
//
//        InterfaceParamDto interfaceParamDto = new InterfaceParamDto();
//        interfaceParamDto.setApi("ofs.shipment.search");
//        interfaceParamDto.setData(JSON.toJSONString(queryOfsSoSaleOutVo));
//        SaleOutReturnMessageDto saleOutReturnMessageDto = (SaleOutReturnMessageDto) ofsUnifiedService.unified(interfaceParamDto);
//        System.out.println(saleOutReturnMessageDto);
//    }

    /**
     * 库存同步，代码同步逻辑
     *
     * @param headerDetailsDtos 查询得到的O出库单对象
     * @author liuyang
     */
    private void implementStock(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtos) throws Exception {
        if (headerDetailsDtos != null) {
            logger.info("TOC销售库存业务：{}行需要进行数据转换", headerDetailsDtos.size());
        }
        if (headerDetailsDtos != null && headerDetailsDtos.size() > 0) {
            try {
                // 查询基本档案
                List<SonDetailsDto> sonDetailsDtoList = queryBasicArchivesStock(headerDetailsDtos);
                // 分组汇总
                Map<String, List<SonDetailsDto>> summaryDimensionMap = groupSummaryStock(sonDetailsDtoList);
                // 查询U8C业务流程
                BdBusitypeEntity bdBusitypeEntity = u8cOperationFlow();
                // 查询销售收发类别
//                BdRdclEntity bdRdclEntity = rdclUtil.queryRdClObject("202");

                if (bdBusitypeEntity != null && summaryDimensionMap != null) {
                    Iterator<Map.Entry<String, List<SonDetailsDto>>> iterator = summaryDimensionMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<String, List<SonDetailsDto>> entry = iterator.next();
                        String keyGroup = entry.getKey();
                        List<SonDetailsDto> oldValue = entry.getValue();
                        HeaderDto header = oldValue.get(0).getHeader();
                        BdCorpEntity bdCorpEntity = oldValue.get(0).getBdCorpEntity();//表头销售公司
                        BdCorpEntity deliverGoodsCorp = oldValue.get(0).getDeliverGoodsCorp();//发货公司
                        BdCalbodyEntity bdCalbodyEntity = oldValue.get(0).getBdCalbodyEntity();//发货仓库组织
                        BdStordocEntity bdStordocEntity = oldValue.get(0).getBdStordocEntity();//发货仓库
                        BdCalbodyEntity bdCalbodyEntity1 = oldValue.get(0).getBdCalbodyEntity1();//收货库存组织
                        BdStordocEntity bdStordocEntity1 = oldValue.get(0).getBdStordocEntity1();//收货仓库
                        BdSalestruEntity bdSalestruEntity = oldValue.get(0).getBdSalestruEntity();//销售组织
                        BdDeptdocEntity bdDeptdocEntity = oldValue.get(0).getBdDeptdocEntity();//业务部门
                        BdCumandocEntity bdCumandocEntity = oldValue.get(0).getBdCumandocEntity();//客商管理档案
                        BdCubasdocEntity bdCubasdocEntity = oldValue.get(0).getBdCubasdocEntity();//客商基本档案
                        BdDefdocEntity platformArchives = oldValue.get(0).getPlatformArchives();//U8C平台档案
                        BdDefdocEntity shopArchives = oldValue.get(0).getShopArchives();//U8C店铺档案
                        BdRdclEntity bdRdclEntity = oldValue.get(0).getBdRdclEntity();//U8C收发类别

                        try {
//                            checkArchives(oldValue.get(0));
                            //生成业务日期
                            String generateBusinessDate = createGenerateBusinessDateStock(header);

                            SaleorderRequestDto saleorderRequestDto = new SaleorderRequestDto();
                            SaleorderRequestParentDto saleorderRequestParentDto = new SaleorderRequestParentDto();
                            saleorderRequestParentDto.setDbilldate(generateBusinessDate);//单据日期
                            saleorderRequestParentDto.setBretinvflag("N");//退货标记
                            saleorderRequestParentDto.setCbiztype(bdBusitypeEntity.getPkBusitype());//业务流程
                            saleorderRequestParentDto.setCcalbodyid(bdCalbodyEntity.getPkCalbody());//库存组织
                            saleorderRequestParentDto.setCcustomerid(bdCumandocEntity.getPkCumandoc());//客户=开票单位=收货单位=表体收货单位=收货单位
                            saleorderRequestParentDto.setCdeptid(bdDeptdocEntity.getPkDeptdoc());//部门
                            saleorderRequestParentDto.setCemployeeid(null);//业务员
                            saleorderRequestParentDto.setCoperatorid(OverallConstant.getOverAllValue("u8cApiZdrPK"));//制单人
                            saleorderRequestParentDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//开票单位
                            saleorderRequestParentDto.setCreceiptcustomerid(bdCumandocEntity.getPkCumandoc());//收货单位
                            saleorderRequestParentDto.setCsalecorpid(bdSalestruEntity.getCsalestruid());//销售组织
                            saleorderRequestParentDto.setCwarehouseid(bdStordocEntity.getPkStordoc());//仓库
                            saleorderRequestParentDto.setDapprovedate(generateBusinessDate);//审核日期
                            saleorderRequestParentDto.setNdiscountrate("100.000000");//整单折扣
                            saleorderRequestParentDto.setPk_corp(bdCorpEntity.getPkCorp());//公司id
                            saleorderRequestParentDto.setVdef17(ProfilesActiveConstant.sourceSystem1);//来源系统

                            //汇总单号=汇总维度
                            saleorderRequestParentDto.setVdef18(keyGroup);

                            //平台
                            saleorderRequestParentDto.setPk_defdoc2(platformArchives.getPkDefdoc());
                            saleorderRequestParentDto.setVdef2(platformArchives.getDocname());

                            //2024年8月8日 17:17:58 店铺档案自定义项1，先不传，后续维护好之后再传!
                            //店铺
                            saleorderRequestParentDto.setPk_defdoc1(shopArchives.getPkDefdoc());
                            saleorderRequestParentDto.setVdef1(shopArchives.getDocname());

                            //收发类别
                            saleorderRequestParentDto.setPk_defdoc3(bdRdclEntity.getPkRdcl());
                            saleorderRequestParentDto.setVdef3(bdRdclEntity.getRdname());

                            saleorderRequestDto.setParentvo(saleorderRequestParentDto);

                            List<SaleorderRequestChildrenDto> saleorderRequestChildrenDtoList = new ArrayList<>();
                            saleorderRequestDto.setChildrenvo(saleorderRequestChildrenDtoList);

                            //把汇总好的出库单明细行合并成一行
                            SonDetailsDto sonDetailsDto = groupMergeDetailedRows(oldValue);

                            //存货管理档案：取发货公司的存货管理档案
//                            BdInvmandocEntity bdInvmandocEntity = queryInventoryMan(sonDetailsDto, bdCalbodyEntity.getPkCorp());
                            BdInvmandocEntity bdInvmandocEntity = sonDetailsDto.getBdInvmandocEntity();

                            //存货基础档案
//                            BdInvbasdocEntity bdInvbasdocEntity = queryStockBasicArchives(bdInvmandocEntity.getPkInvmandoc(), deliverGoodsCorp.getPkCorp());
                            BdInvbasdocEntity bdInvbasdocEntity = sonDetailsDto.getBdInvbasdocEntity();

                            //根据存货基础档案编码，查询当前存货的税率
//                            BdTaxitemsEntity bdTaxitemsEntity1 = queryBdTaxitems(bdInvbasdocEntity.getInvcode());
                            BdTaxitemsEntity bdTaxitemsEntity1 = sonDetailsDto.getBdTaxitemsEntity();

                            String tax = "0." + new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString();
                            BigDecimal noriginalcurprice = null;//无税单价
                            BigDecimal noriginalcurmny = null;//无税金额
                            BigDecimal noriginalcurtaxprice = null;//含税单价
                            BigDecimal noriginalcursummny = null;//价税合计
                            BigDecimal noriginalcurtaxmny = null;//税额
                            try {
                                noriginalcurtaxprice = sonDetailsDto.getGroupTotalPayAmount().divide(sonDetailsDto.getGroupShipQty(), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                noriginalcurprice = noriginalcurtaxprice.divide(new BigDecimal(1).add(new BigDecimal(tax)), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                noriginalcurmny = noriginalcurprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                noriginalcursummny = noriginalcurtaxprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                noriginalcurtaxmny = noriginalcursummny.subtract(noriginalcurmny).setScale(2, BigDecimal.ROUND_HALF_UP);
                            } catch (Exception e) {
                                logger.error("TOC金额计算错误", e);
                                Assert.state(false, "金额计算错误，原因：{}" + e.getMessage());
                            }

                            //判断是否为赠品
                            Boolean isblargessflag = false;
                            if (noriginalcursummny.longValue() == 0) {
                                isblargessflag = true;
                            }

                            SaleorderRequestChildrenDto saleorderRequestChildrenDto = new SaleorderRequestChildrenDto();
                            saleorderRequestChildrenDto.setBlargessflag(isblargessflag);//是否赠品
                            saleorderRequestChildrenDto.setCadvisecalbodyid(bdCalbodyEntity.getPkCalbody());//发货库存组织
                            saleorderRequestChildrenDto.setCbodywarehouseid(bdStordocEntity.getPkStordoc());//发货仓库
                            saleorderRequestChildrenDto.setCbodywarehousecode(bdStordocEntity.getStorcode());//发货仓库编码：这个字段不需要给openapi接口，而是提供给下游方法使用
                            saleorderRequestChildrenDto.setCconsigncorpid(deliverGoodsCorp.getPkCorp());//发货公司
                            saleorderRequestChildrenDto.setCcurrencytypeid("00010000000000000001");//币种
                            saleorderRequestChildrenDto.setCinventoryid(bdInvmandocEntity.getPkInvmandoc());//存货id
                            saleorderRequestChildrenDto.setCinventorycode(bdInvbasdocEntity.getInvcode());//存货编码
                            saleorderRequestChildrenDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//收货单位
                            saleorderRequestChildrenDto.setDconsigndate(generateBusinessDate);//计划发货日期
                            saleorderRequestChildrenDto.setDdeliverdate(generateBusinessDate);//要求收货日期
                            saleorderRequestChildrenDto.setNexchangeotobrate("1.00000000");//折本汇率
                            saleorderRequestChildrenDto.setNitemdiscountrate("100.000000");//单品折扣
                            saleorderRequestChildrenDto.setNnumber(String.valueOf(sonDetailsDto.getGroupShipQty()));//数量
                            saleorderRequestChildrenDto.setNoriginalcurdiscountmny("0");//折扣额
                            saleorderRequestChildrenDto.setNoriginalcurmny(noriginalcurmny.stripTrailingZeros().toPlainString());//无税金额
//                            saleorderRequestChildrenDto.setNoriginalcurnetprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税净价
//                            saleorderRequestChildrenDto.setNoriginalcurprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税单价
                            saleorderRequestChildrenDto.setNoriginalcursummny(noriginalcursummny.stripTrailingZeros().toPlainString());//价税合计
                            saleorderRequestChildrenDto.setNoriginalcurtaxmny(noriginalcurtaxmny.stripTrailingZeros().toPlainString());//税额
                            saleorderRequestChildrenDto.setNoriginalcurtaxnetprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税净价
                            saleorderRequestChildrenDto.setNoriginalcurtaxprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税单价
                            saleorderRequestChildrenDto.setNtaxrate(new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString());//税率
//                            saleorderRequestChildrenDto.setCreccalbodyid(bdCalbodyEntity1.getPkCalbody());//收货库存组织：2024年8月7日 16:21:48 和佳妮、道品一起测试，收货库存组织、收货仓库 是不需要传递的
//                            saleorderRequestChildrenDto.setCrecwareid(bdStordocEntity1.getPkStordoc());//收货仓库
                            saleorderRequestChildrenDtoList.add(saleorderRequestChildrenDto);

                            //销售订单单据推送到u8c
                            List<SaleorderRequestDto> saleorderRequestDtoList = new ArrayList<>();
                            saleorderRequestDtoList.add(saleorderRequestDto);

                            Map<String, List<SaleorderRequestDto>> stringStringMap = new HashMap<>();
                            stringStringMap.put("saleorder", saleorderRequestDtoList);
                            SoSaleResultRootDto soSaleResultRootDto = sendU8CTOCOrder(JSON.toJSONString(stringStringMap));
                            String vreceiptcode = null;
                            String pk_corp = null;
                            String csaleid = null;
                            if (soSaleResultRootDto != null && soSaleResultRootDto.getParentvo() != null) {
                                vreceiptcode = soSaleResultRootDto.getParentvo().getVreceiptcode();
                                pk_corp = soSaleResultRootDto.getParentvo().getPk_corp();
                                csaleid = soSaleResultRootDto.getParentvo().getCsaleid();
                            }
                            logger.info("销售订单编号：{} 主键：{} 销售公司：{}", vreceiptcode, csaleid, pk_corp);
                            //记录成功
                            //日志推送的详情，两种方法，是推送U8C成功之后记录，还是整理推送完毕后再记录？
                            //护童项目之前是整体推送之前记录，后来抛出链接失效的异常，而且只有程序执行完毕后，才能体现结果，执行过程中无法发现结果
                            //所以还是需要等待U8C接口推送成功之后，马上发生信息的记录，时间下来这样足够稳定，同步速度上没有大的问题
                            updateSuccessOrFail1(oldValue, "Y", "success", vreceiptcode, csaleid);
                        } catch (Exception e) {
                            logger.error("TOC业务转换成U8C对象过程中、或者单据推送到U8C出现异常！", e);
                            //记录失败
                            String message = e.getMessage();
                            if (message == null) {
                                message = "未知错误";
                            }
                            updateSuccessOrFail1(oldValue, "N", message, null, null);
                        }
                    }
                } else {
                    //2024年8月6日 11:28:54此处不记录失败，不认为是错误
                    logger.info("summaryDimensionMap变量或者bdBusitypeEntity变量为空，因此主要的推送逻辑不会被执行！");
                }
            } catch (Exception e) {
                logger.error("外层转换逻辑抛出异常", e);
                // 记录失败
            }
        } else {
            logger.error("TOC库存同步，没有需要同步的数据行！");
        }
    }

    /**
     * 2024年7月31日 10:34:09
     * 生成业务日期，以发货时间作为业务日期
     *
     * @author liuyang
     */
    private String createGenerateBusinessDateStock(com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto header) {
        //TODO 测试
//        header.setShipAt("2024-09-14");
        if (header != null && header.getShipAt() != null) {
            //TOC以出库日期作为业务日期
            String shipAt = header.getShipAt();
            String businessFormat = null;
            try {
                Date dbill = DateUtil.parse(shipAt);
                businessFormat = DateUtil.format(dbill, "yyyy-MM-dd");
            } catch (Exception e) {
//                e.printStackTrace();
                logger.error("业务日期转换失败", e);
                Assert.state(false, "业务日期生成失败，原因：", e);
            }
            return businessFormat;
        } else {
            logger.error("生成出库日期失败，或者shipAt为空! json：{}", JSON.toJSON(header));
            Assert.state(false, "生成出库日期失败，或者shipAt为空! json：{}", JSON.toJSON(header));
            return null;
        }
    }

    /**
     * 2024年9月4日 14:46:28
     * 生成业务日期，以交易成功时间作为业务日期
     *
     * @author liuyang
     */
    private String createGenerateBusinessDateTran(com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto header) {
        if (header != null && header.getTradeSuccessAt() != null) {
            //TOC以出库日期作为业务日期
            String tradeSuccessAt = header.getTradeSuccessAt();
            String businessFormat = null;
            try {
                Date dbill = DateUtil.parse(tradeSuccessAt);
                businessFormat = DateUtil.format(dbill, "yyyy-MM-dd");
            } catch (Exception e) {
//                e.printStackTrace();
                logger.error("业务日期转换失败", e);
                Assert.state(false, "业务日期生成失败，原因：", e);
            }
            return businessFormat;
        } else {
            logger.error("生成出库日期失败，或者tradeSuccessAt为空! json：{}", JSON.toJSON(header));
            Assert.state(false, "生成出库日期失败，或者tradeSuccessAt为空! json：{}", JSON.toJSON(header));
            return null;
        }
    }


    /**
     * 档案转换
     * 2024年9月4日 14:11:28 库存同步、确认收入同步是可以共用这个方法的
     *
     * @author liuyang
     */
    private List<SonDetailsDto> queryBasicArchivesStock(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) {
        List<SonDetailsDto> sonDetailsDtoList = new ArrayList<>();
        List<ErrorHeaderDetailsDtoDto> errorHeaderDetailsDtoDtoList = new ArrayList<>();

        if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
            try {
                //初始化档案缓存
                CacheTocMapVo cacheTocMapVo = basicArchivesCacheUtil.initCache(headerDetailsDtoList);
                //查询对应的OFS销售订单
                List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto> headerDetailsDtos = queryOfsOrder(headerDetailsDtoList);
                findMatchingOfsOrder(headerDetailsDtos, headerDetailsDtoList);

                for (int i = 0; i < headerDetailsDtoList.size(); i++) {
                    HeaderDetailsDto headerDetailsDto = headerDetailsDtoList.get(i);
                    HeaderDto header = headerDetailsDto.getHeader();
                    List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto> details = headerDetailsDto.getDetails();
                    try {
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto headerDetailsDto1 = header.getHeaderDetailsDto();
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDto header1 = headerDetailsDto1.getHeader();
                        List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.DetailsDto> details1 = headerDetailsDto1.getDetails();

                        //OFS销售订单
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto headerDetailsDto2 = header.getHeaderDetailsDto();
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDto header2 = headerDetailsDto2.getHeader();

                        //TOC、TOB业务已经和万确认，如果没有，则默认为「SALES销售」
                        if (header2.getSubOrderType() == null || "".equals(header2.getSubOrderType())) {
                            header2.setSubOrderType("SALES");
                        }
                        BdRdclEntity bdRdclEntity = cacheTocMapVo.getStringBdRdclEntityMap().get(header2.getSubOrderType());
                        Assert.notNull(bdRdclEntity, "根据业务类型({})没有匹配到U8C业务类型", header2.getSubOrderType());

                        //表头公司：通过名称匹配U8C公司
//                    String corpName = "上海丽知品牌管理有限公司";
                        String companyCode = header.getCompanyCode();
                        //TODO 测试
//                        companyCode = "SHLZ";
                        Assert.notNull(companyCode, "O出库单表头货主不能为空！");
                        BdCorpEntity bdCorpEntity = cacheTocMapVo.getStringBdCorpEntityMap().get(companyCode);
                        Assert.notNull(bdCorpEntity, "根据公司编码({})没有匹配到U8C公司档案(公司编码=O货主)", companyCode);

                        //发货库存组织
                        BdCalbodyEntity bdCalbodyEntity = cacheTocMapVo.getStringBdCalbodyEntityMap().get(bdCorpEntity.getPkCorp());
                        Assert.notNull(bdCalbodyEntity, "根据公司主键没有查询到发货库存组织 公司主键：{}", bdCorpEntity.getPkCorp());

                        //发货公司，暂时把O表头公司作为发货公司，正常情况下需要把O库存地点对于的公司作为发货公司

                        //发货仓库
                        //2024年8月5日 15:06:38 仓库O与U两边仓库编码是一致的，和妮姐确认过了
                        String facilityCode = header.getFacilityCode();
                        Assert.notNull(facilityCode, "O仓库编码不能为空");
                        BdStordocEntity bdStordocEntity = cacheTocMapVo.getStringBdStordocEntityMap().get(facilityCode + bdCalbodyEntity.getPkCalbody());
                        Assert.notNull(bdStordocEntity, "没有匹配到发货仓库 发货库存组织主键：{} O库存地点编码：{}", facilityCode, bdCalbodyEntity.getPkCalbody());

                        //2024年8月5日 15:25:07 收货库存组织、收货仓库、默认和发货库存组织、发货仓库一致，已经和佳妮确认
                        //收货库存组织：速网来看收货库存组织对应表头工具
                        //收货仓库：通过收货库存组织+仓库编码，确定收货仓库

                        //销售组织2024年8月5日 15:33:40 和妮姐确认，销售组织和表头公司，作为一对一的关系，
                        BdSalestruEntity bdSalestruEntity = cacheTocMapVo.getStringBdSalestruEntityMap().get(bdCorpEntity.getUnitname());
                        Assert.notNull(bdSalestruEntity, "无匹配到销售组织 表头公司名称：{}", bdCorpEntity.getUnitname());

                        //业务部门：暂定的部门名称：其他，2024年8月5日 15:39:42 已经和妮姐确认
                        BdDeptdocEntity bdDeptdocEntity = cacheTocMapVo.getStringBdDeptdocEntityMap().get(bdCorpEntity.getPkCorp());
                        Assert.notNull(bdDeptdocEntity, "无法匹配到业务部门 部门名称：其他 对应公司名称：{}", bdCorpEntity.getPkCorp());

                        //客商基本档案
                        // 2024年8月8日 12:05:10 O店铺的业务编码=U8C客商自定义项1，O没有店铺信息查询接口，因此无法通过出库单的店铺编码，查询到O店铺档案对应的业务编码，接口上线之后需要补充这一部分逻辑
//                    String custName = "天猫intoyou旗舰店-自营";
                        String storeCode = header.getStoreCode();
                        Assert.notNull(storeCode, "O店铺编码不能为空，没有办法完成业务逻辑！");
                        Assert.state(!"".equals(storeCode.trim()), "O店铺编码不能为空，没有办法完成业务逻辑！");
                        BdCubasdocEntity bdCubasdocEntity = cacheTocMapVo.getStringBdCubasdocEntityMap().get(storeCode);
                        Assert.notNull(bdCubasdocEntity, "根据U8C客商基本档案def1(记录o店铺编码),无法匹配到客户档案 o店铺编码：{}", storeCode);

                        //客商管理档案：2024年8月5日 15:41:54 TOC店铺名称查询U8C客商档案，已经和妮姐确认
                        //2024年8月5日 15:49:49 先根据O店铺编码，得到店铺档案信息，取到名称，通过U8C接口查询出来
                        //目前O店铺信息查询接口还没有，等待开发，所以我这里先写所一个名字
                        BdCumandocEntity bdCumandocEntity = cacheTocMapVo.getStringBdCumandocEntityMap().get(bdCubasdocEntity.getPkCubasdoc() + bdCorpEntity.getPkCorp());
                        Assert.notNull(bdCumandocEntity, "无法匹配到客商档案 店铺名称：{}", "天猫intoyou旗舰店-自营");

                        //查找平台
                        BdDefdocEntity bdDefdocEntity = cacheTocMapVo.getStringBdDefdocPlatformEntityMap().get(header.getSourcePlatformCode());
                        Assert.notNull(bdDefdocEntity, "根据O平台编码({})无法匹配到U8C平台自定义档案", header.getSourcePlatformCode());

                        //查找店铺
                        BdDefdocEntity bdDefdocEntity1 = cacheTocMapVo.getStringBdDefdocShopEntityMap().get(header.getStoreCode());
                        Assert.notNull(bdDefdocEntity1, "根据O店铺编码({})无法匹配到U8C店铺自定义档案", header.getStoreCode());

                        //字段拷贝
                        for (int j = 0; j < details.size(); j++) {
                            DetailsDto detailsDto = details.get(j);

                            //存货基本档案
                            BdInvbasdocEntity bdInvbasdocEntity = cacheTocMapVo.getStringBdInvbasdocEntityMap().get(detailsDto.getSkuCode());
                            Assert.notNull(bdInvbasdocEntity, "无法匹配到存货基本档案 存货管理主键：{} 公司：{}", detailsDto.getSkuCode(), bdCorpEntity.getPkCorp());
                            //存货管理档案，是发货公司的存货档案
                            BdInvmandocEntity bdInvmandocEntity = cacheTocMapVo.getStringBdInvmandocEntityMap().get(detailsDto.getSkuCode() + bdCorpEntity.getPkCorp());
                            Assert.notNull(bdInvmandocEntity, "无法匹配到存货管理档案 货品sku：{} 公司：{}", detailsDto.getSkuCode(), bdCorpEntity.getPkCorp());
                            //存货税率
                            BdTaxitemsEntity bdTaxitemsEntity = cacheTocMapVo.getStringBdTaxitemsEntityMap().get(bdInvmandocEntity.getInvcode());
                            Assert.notNull(bdTaxitemsEntity, "无法匹配到存货税率 存货编码：{}", bdInvmandocEntity.getInvcode());

                            //2024年8月6日 10:16:22 通过O出库单的表头，查询得出U8C档案，放在表体的原因是方便分组汇总
                            //下一个步骤的分组汇总，是通过表体明细完成的
                            SonDetailsDto sonDetailsDto = new SonDetailsDto();
                            sonDetailsDto.setHeader(header);
                            sonDetailsDto.setBdCorpEntity(bdCorpEntity);
                            sonDetailsDto.setDeliverGoodsCorp(bdCorpEntity);
                            sonDetailsDto.setBdCalbodyEntity(bdCalbodyEntity);
                            sonDetailsDto.setBdStordocEntity(bdStordocEntity);
                            sonDetailsDto.setBdCalbodyEntity1(bdCalbodyEntity);
                            sonDetailsDto.setBdStordocEntity1(bdStordocEntity);
                            sonDetailsDto.setBdSalestruEntity(bdSalestruEntity);
                            sonDetailsDto.setBdDeptdocEntity(bdDeptdocEntity);
                            sonDetailsDto.setBdCumandocEntity(bdCumandocEntity);
                            sonDetailsDto.setBdCubasdocEntity(bdCubasdocEntity);
                            sonDetailsDto.setPlatformArchives(bdDefdocEntity);
                            sonDetailsDto.setShopArchives(bdDefdocEntity1);
                            sonDetailsDto.setBdInvmandocEntity(bdInvmandocEntity);
                            sonDetailsDto.setBdInvbasdocEntity(bdInvbasdocEntity);
                            sonDetailsDto.setBdTaxitemsEntity(bdTaxitemsEntity);
                            sonDetailsDto.setHeaderDetailsDto(headerDetailsDto1);
                            sonDetailsDto.setBdRdclEntity(bdRdclEntity);

                            BeanUtil.copyPropertiesV2(detailsDto, sonDetailsDto);
                            sonDetailsDtoList.add(sonDetailsDto);
                        }
                    } catch (Exception e) {
                        logger.error("档案转换抛出异常", e);
                        String message = e.getMessage();
                        if (message == null) {
                            message = "未知错误";
                        }
                        //失败
                        ErrorHeaderDetailsDtoDto errorHeaderDetailsDtoDto = new ErrorHeaderDetailsDtoDto();
                        errorHeaderDetailsDtoDto.setNewPushDate(getNewDateStr());
                        errorHeaderDetailsDtoDto.setNewTransmitInfo(message);
                        errorHeaderDetailsDtoDto.setNewstate("N");
                        errorHeaderDetailsDtoDto.setHeader(header);
                        errorHeaderDetailsDtoDto.setDetails(details);
                        errorHeaderDetailsDtoDtoList.add(errorHeaderDetailsDtoDto);
                    }
                }
                //成功
            } catch (Exception e) {
                //失败，这一块逻辑，前期稳定后，不需要太关注，主要是一些基础档案的查询生成Map
                logger.error("OFS销售出库单关联查询U8C档案失败", e);
            }
        } else {
            logger.info("queryBasicArchives方法headerDetailsDtoList.size为0");
        }

        //批量把错误写入到日志信息表
        if (errorHeaderDetailsDtoDtoList.size() > 0) {
            updateFailOrSuccessTocofsSaleoutDetailedArchiveInquiry(errorHeaderDetailsDtoDtoList);
        }
        return sonDetailsDtoList;
    }

    /**
     * bean copy
     * 2024年7月31日 10:34:09
     */
    private List<TocofsSaleoutEntity> copyHeaderDto(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto> headerDtoList) {
        List<TocofsSaleoutEntity> tocofsSaleoutEntityList = new ArrayList<>();
        if (headerDtoList != null && headerDtoList.size() > 0) {
            for (int i = 0; i < headerDtoList.size(); i++) {
                com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDto headerDto = headerDtoList.get(i);
                TocofsSaleoutEntity tocofsSaleoutEntity = new TocofsSaleoutEntity();
//                BeanUtils.copyProperties(headerDto, tocofsSaleoutEntity);
                BeanUtil.copyPropertiesV2(headerDto, tocofsSaleoutEntity);
                tocofsSaleoutEntityList.add(tocofsSaleoutEntity);
            }
        }
        return tocofsSaleoutEntityList;
    }

    /**
     * bean copy
     * 2024年8月2日 16:04:11
     */
    private List<TocofsSaleoutDetailedEntity> copyDetailsDto(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto> detailsDtos) {
        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityArrayList = new ArrayList<>();
        if (detailsDtos != null && detailsDtos.size() > 0) {
            for (int i = 0; i < detailsDtos.size(); i++) {
                com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.DetailsDto detailsDto = detailsDtos.get(i);
                TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
//                tocofsSaleoutDetailedEntity.setBusinessType("TOC_ORDER");
//                BeanUtils.copyProperties(detailsDto, tocofsSaleoutDetailedEntity);

                BeanUtil.copyPropertiesV2(detailsDto, tocofsSaleoutDetailedEntity);
                //补充一些业务字段
                createPrimaryKeyAndBusinessDateAndBusinessType(tocofsSaleoutDetailedEntity, detailsDto);
                tocofsSaleoutDetailedEntityArrayList.add(tocofsSaleoutDetailedEntity);
            }
        }
        return tocofsSaleoutDetailedEntityArrayList;
    }

    /**
     * 分组汇总：公司+店铺+仓库+SKU+收发类别+部门，数量合并相加
     *
     * @param sonDetailsDtoList 整理好的数据
     *                          filterType        0或者其他、不过滤，1 过滤交易成功红、2过滤交易成功蓝
     * @author liuyang
     */
    private Map<String, List<SonDetailsDto>> groupSummaryStock(List<SonDetailsDto> sonDetailsDtoList) {
        if (sonDetailsDtoList != null && sonDetailsDtoList.size() > 0) {
//            switch (filterType) {
//                case "1":
//                    sonDetailsDtoList = sonDetailsDtoList.stream().filter(sonDetailsDto -> "Y".equals(sonDetailsDto.getNewState2())).collect(Collectors.toList());
//                    break;
//                case "2":
//                    sonDetailsDtoList = sonDetailsDtoList.stream().filter(sonDetailsDto -> "Y".equals(sonDetailsDto.getNewState3())).collect(Collectors.toList());
//                    break;
//            }
            for (int i = 0; i < sonDetailsDtoList.size(); i++) {
                SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(i);
                //2024年8月6日 10:35:25表头对象用于带出表头相关的分组汇总信息
                HeaderDto header = sonDetailsDto.getHeader();

                //公司
                BdCorpEntity bdCorpEntity = sonDetailsDto.getBdCorpEntity();
                //店铺（主要是店铺编码）
                String storeCode = header.getStoreCode();
                //仓库
                String facilityCode = header.getFacilityCode();
                //SKU
                String skuCode = sonDetailsDto.getSkuCode();
                //出库类型（内购）
//                String refOrderType = header.getRefOrderType();
                //收发类别
                BdRdclEntity bdRdclEntity = sonDetailsDto.getBdRdclEntity();

                StringBuffer summaryDimensionStr = new StringBuffer();
                if (bdCorpEntity != null && bdCorpEntity.getPkCorp() != null) {
                    summaryDimensionStr.append(bdCorpEntity.getPkCorp());
                } else {
                    summaryDimensionStr.append(NOTHING);
                }
                summaryDimensionStr.append(ADD);

                if (storeCode != null && !"".equals(storeCode)) {
                    summaryDimensionStr.append(storeCode);
                } else {
                    summaryDimensionStr.append(NOTHING);
                }
                summaryDimensionStr.append(ADD);

                if (facilityCode != null && !"".equals(facilityCode)) {
                    summaryDimensionStr.append(facilityCode);
                } else {
                    summaryDimensionStr.append(NOTHING);
                }
                summaryDimensionStr.append(ADD);

                if (skuCode != null && !"".equals(skuCode)) {
                    summaryDimensionStr.append(skuCode);
                } else {
                    summaryDimensionStr.append(NOTHING);
                }
                summaryDimensionStr.append(ADD);

//                if (refOrderType != null && !"".equals(refOrderType)) {
//                    summaryDimensionStr.append(refOrderType);
//                } else {
//                    summaryDimensionStr.append(NOTHING);
//                }
                if (bdRdclEntity != null && bdRdclEntity.getRdcode() != null) {
                    summaryDimensionStr.append(bdRdclEntity.getRdcode());
                } else {
                    summaryDimensionStr.append(NOTHING);
                }
                //TODO 部门？O还未开发好，待定

                sonDetailsDto.setSummaryDimensionStr(summaryDimensionStr.toString());
            }
            logger.info("TOC：{}个出库单对象需要汇总", sonDetailsDtoList.size());
            return sonDetailsDtoList.stream().collect(Collectors.groupingBy(SonDetailsDto::getSummaryDimensionStr));
        }
        logger.info("TOC：0个对象需要汇总");
        return null;
    }

    /**
     * 2024年8月6日 10:59:03 查询U8C业务流程
     *
     * @author liuyang
     */
    private BdBusitypeEntity u8cOperationFlow() throws Exception {
        //查询业务流程
        //2024年8月6日 11:33:07 具体的业务流程名称，还需要实施提供
        String processName = "TOC销售";
        BdBusitypeEntity bdBusitypeEntity = queryBdBusitypeUtil.queryBdBusitype(processName);
        Assert.notNull(bdBusitypeEntity, "根据业务流程名称({})没有查询到业务流程", processName);
        return bdBusitypeEntity;
    }

    /**
     * 2024年8月6日 10:59:03 查询U8C业务流程
     *
     * @author liuyang
     */
    private BdBusitypeEntity u8cOperationFlowV2() throws Exception {
        String processName = "TOC冲发出商品";
        BdBusitypeEntity bdBusitypeEntity = queryBdBusitypeUtil.queryBdBusitype(processName);
        Assert.notNull(bdBusitypeEntity, "根据业务流程名称({})没有查询到业务流程", processName);
        return bdBusitypeEntity;
    }

    /**
     * 2024年8月6日 10:59:03 查询U8C业务流程
     *
     * @author liuyang
     */
    private BdBusitypeEntity u8cOperationFlowV3() throws Exception {
        String processName = "TOC确认收入";
        BdBusitypeEntity bdBusitypeEntity = queryBdBusitypeUtil.queryBdBusitype(processName);
        Assert.notNull(bdBusitypeEntity, "根据业务流程名称({})没有查询到业务流程", processName);
        return bdBusitypeEntity;
    }

    /**
     * 检查参数是否为空
     * 2024年8月6日 11:40:19 保险的做法，最好还是验证一下
     *
     * @author liuyang
     */
//    private void checkArchives(SonDetailsDto sonDetailsDto) {
//        Assert.notNull(sonDetailsDto, "sonDetailsDto不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getHeader(), "header对象不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdCorpEntity(), "表头公司不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdCalbodyEntity(), "发货库存组织不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdStordocEntity(), "发货仓库不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdCalbodyEntity1(), "收货库存组织不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdStordocEntity1(), "收货库存不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdSalestruEntity(), "销售组织不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdDeptdocEntity(), "业务部门不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//        Assert.notNull(sonDetailsDto.getBdCumandocEntity(), "客商档案不能为空 对象json：{}", JSON.toJSONString(sonDetailsDto));
//    }

    /**
     * 查询存货管理档案
     *
     * @param pkCorp        发货公司主键
     * @param sonDetailsDto 出库单存货明细行
     * @author liuyang
     */
//    private BdInvmandocEntity queryInventoryMan(SonDetailsDto sonDetailsDto, String pkCorp) {
//        Assert.notNull(sonDetailsDto, "sonDetailsDto不能为空");
//        Assert.notNull(sonDetailsDto.getSkuCode(), "O存货商家编码不能为空");
//        Assert.notNull(pkCorp, "发货公司主键不能为空");
//
//        BdInvmandocEntity bdInvmandocEntity = TocOrderBasicArchivesCacheUtil.stringBdInvmandocEntityMap.get(sonDetailsDto.getSkuCode() + pkCorp);
//        Assert.notNull(bdInvmandocEntity, "无法匹配到存货管理档案 存货商家编码：{} 存货发货公司：{}", sonDetailsDto.getSkuCode(), pkCorp);
//        return bdInvmandocEntity;
//    }

    /**
     * 合并明细行
     * 单价计算公式：sum(实付金额/实发数量) 最后除以条数
     *
     * @author liuyang
     */
    private SonDetailsDto groupMergeDetailedRows(List<SonDetailsDto> sonDetailsDtoList) throws Exception {
        if (sonDetailsDtoList != null && sonDetailsDtoList.size() > 0) {
            BigDecimal groupTotalPayAmount = new BigDecimal("0");
            BigDecimal groupShipQty = new BigDecimal("0");

            for (int i = 0; i < sonDetailsDtoList.size(); i++) {
                SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(i);

                //实付金额/实发数量
                Assert.notNull(sonDetailsDto.getTotalPayAmount(), "实付金额不能为空 明细行对象:{}", JSON.toJSONString(sonDetailsDto));
                Assert.notNull(sonDetailsDto.getShipQty(), "实发数量不能为空  明细行对象:{}", JSON.toJSONString(sonDetailsDto));
                BigDecimal totalPayAmountBigDecimal = new BigDecimal(sonDetailsDto.getTotalPayAmount());
                BigDecimal shipQtyBigDecimal = new BigDecimal(sonDetailsDto.getShipQty());

                groupTotalPayAmount = groupTotalPayAmount.add(totalPayAmountBigDecimal);
                groupShipQty = groupShipQty.add(shipQtyBigDecimal);
            }
            SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(0);
            sonDetailsDto.setGroupShipQty(groupShipQty);
            sonDetailsDto.setGroupTotalPayAmount(groupTotalPayAmount);
            logger.info("{}个明细行发生了合并！", sonDetailsDtoList.size());
            return sonDetailsDto;
        } else {
            logger.info("sonDetailsDtoList集合是空的！");
        }
        return null;
    }

    /**
     * 2024年8月7日 10:25:29
     * 查询基础档案，根据公司、管理档案主键查询
     *
     * @author liuyang
     */
//    private BdInvbasdocEntity queryStockBasicArchives(String pkInvmandoc, String pkCorp) {
//        Assert.notNull(pkInvmandoc, "存货管理档案不能为空");
//        Assert.notNull(pkCorp, "公司档案不能为空");
//        BdInvbasdocEntity bdInvbasdocEntity = TocOrderBasicArchivesCacheUtil.stringBdInvbasdocEntityHashMap.get(pkInvmandoc + pkCorp);
//        Assert.notNull(bdInvbasdocEntity, "根据公司主键：{} 和存货管理档案主键：{} 没有查询到存货基本档案", pkCorp, pkInvmandoc);
//        return bdInvbasdocEntity;
//    }

    /**
     * 2024年8月7日 14:58:34
     * 查询税目档案
     *
     * @author liuyang
     */
//    private BdTaxitemsEntity queryBdTaxitems(String invcode) {
//        Assert.notNull(invcode, "存货编码不能为空");
//        BdTaxitemsEntity bdTaxitemsEntity = TocOrderBasicArchivesCacheUtil.stringBdTaxitemsEntityHashMap.get(invcode);
//        Assert.notNull(bdTaxitemsEntity, "根据存货编码({})，无法匹配到税率！", invcode);
//        return bdTaxitemsEntity;
//    }

    /**
     * 2024年8月8日 10:54:48
     * 推送U8C销售订单方法
     *
     * @author liuyang
     */
    public SoSaleResultRootDto sendU8CTOCOrder(String param) throws Exception {
        long startLong = System.currentTimeMillis();
        logger.info("TOC推送开始，推送参数：" + param + ",U8C_URL:" + OverallConstant.getOverAllValue("u8c_url"));
        String apiCode = "8000370006";
        String result = HttpRequest.post(OverallConstant.getOverAllValue("u8c_url")).header("appId", OverallConstant.getOverAllValue("appId"))//头信息，多个头信息多次调用此方法即可
                .header("usercode", OverallConstant.getOverAllValue("u8cApiUsercodePK")).header("password", OverallConstant.getOverAllValue("u8cApiPasswordPK")).header("system", OverallConstant.getOverAllValue("u8cApiSystemPK")).header("trantype", OverallConstant.getOverAllValue("u8cApiTrantypePK")).header("apiCode", apiCode)//头信息，多个头信息多次调用此方法即可
                .header("publicKey", OverallConstant.getOverAllValue("publicKey"))//头信息，多个头信息多次调用此方法即可
                .header("secretKey", OverallConstant.getOverAllValue("secretKey"))//头信息，多个头信息多次调用此方法即可
                .body(param)//表单内容
                .timeout(600000)//超时，毫秒
                .execute().body();
        logger.info("TOC推送结束，返回参数：" + result);
        long endLong = System.currentTimeMillis();
        logger.info("TOC接口请求耗时：" + (endLong - startLong));

        JSONObject jsonObject = JSON.parseObject(result);
        result = String.valueOf(jsonObject.get("attribute"));

        boolean isSuccess = false;
        SoSaleResultRootDto soSaleResultRootDto = null;
        if (result != null && !"".equals(result)) {
            ReusltStrDto reusltStrDto = JSON.parseObject(result, ReusltStrDto.class);
            if ("success".equals(reusltStrDto.getStatus())) {
                soSaleResultRootDto = resultDataHandle(reusltStrDto.getData());
                isSuccess = true;
            }
        }
        if (!isSuccess) {
            Assert.state(false, "TOC业务O出库单推送U8C销售订单失败 接口返回结果：{}", result);
        }
        return soSaleResultRootDto;
    }

    /**
     * 返回结果解析处理，在确认了success后调用
     *
     * @author liuyang
     */
    private SoSaleResultRootDto resultDataHandle(String resultData) {
        try {
            if (resultData != null && !"".equals(resultData)) {
                if (resultData.contains("[")) {
                    resultData = resultData.substring(1, resultData.length() - 1);
                }
                return JSON.parseObject(resultData, SoSaleResultRootDto.class);
            }
        } catch (Exception e) {
//            e.printStackTrace();
            logger.error("解析返回参数失败的错误", e);
            //如果解析失败，记录原因，但是不能影响结果的记录
        }
        return null;
    }

    /**
     * 2024年8月15日 17:08:42
     * 填充主表主键、业务日期、业务类型
     */
    private void createPrimaryKeyAndBusinessDateAndBusinessType(TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity, DetailsDto detailsDto) {
        if (tocofsSaleoutDetailedEntity != null && detailsDto != null && detailsDto.getHeaderDto() != null) {
            HeaderDto headerDto = detailsDto.getHeaderDto();

            if (headerDto.getId() != null) {
                tocofsSaleoutDetailedEntity.setMaintableid(headerDto.getId());//主表主键
            }
            if (headerDto.getShipAt() != null) {
                tocofsSaleoutDetailedEntity.setBusinessdate(headerDto.getShipAt());//业务日期-出库时间
            }
            if (headerDto.getTradeSuccessAt() != null) {
                tocofsSaleoutDetailedEntity.setSuccessfultradedate(headerDto.getTradeSuccessAt());//业务日期-交易时间
            }
            tocofsSaleoutDetailedEntity.setBusinesstype("TOC_ORDER");//业务类型
        } else {
            logger.info("createPrimaryKeyAndBusinessDateAndBusinessType方法存在false！");
        }
    }

    /**
     * 库存同步，代码同步逻辑
     *
     * @param headerDetailsDtos 查询得到的O出库单对象
     * @author liuyang
     */
    private void implementTran(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtos) throws Exception {
        logger.info("TOC销售库存业务：{}行需要进行数据转换", headerDetailsDtos.size());

        if (headerDetailsDtos != null && headerDetailsDtos.size() > 0) {
            try {
                //查询基本档案
                List<SonDetailsDto> sonDetailsDtoList = queryBasicArchivesStock(headerDetailsDtos);
                //分组汇总：红蓝
                Map<String, List<SonDetailsDto>> summaryDimensionMap = groupSummaryStock(sonDetailsDtoList);
                //分组汇总：蓝
//                Map<String, List<SonDetailsDto>> summaryDimensionMap2 = groupSummaryStock(sonDetailsDtoList, "2");

                //TOC业务流程-TOC冲回发出商品
                BdBusitypeEntity bdBusitypeEntity = u8cOperationFlowV2();
                //TOC业务流程-TOC确认收入
                BdBusitypeEntity bdBusitypeEntity2 = u8cOperationFlowV3();
                //查询销售收发类别
//                BdRdclEntity bdRdclEntity = rdclUtil.queryRdClObject("202");

                if (bdBusitypeEntity != null && summaryDimensionMap != null) {
                    Iterator<Map.Entry<String, List<SonDetailsDto>>> iterator = summaryDimensionMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<String, List<SonDetailsDto>> entry = iterator.next();
                        String keyGroup = entry.getKey();
                        List<SonDetailsDto> oldValue = entry.getValue();
                        HeaderDto header = oldValue.get(0).getHeader();
                        BdCorpEntity bdCorpEntity = oldValue.get(0).getBdCorpEntity();//表头销售公司
                        BdCorpEntity deliverGoodsCorp = oldValue.get(0).getDeliverGoodsCorp();//发货公司
                        BdCalbodyEntity bdCalbodyEntity = oldValue.get(0).getBdCalbodyEntity();//发货仓库组织
                        BdStordocEntity bdStordocEntity = oldValue.get(0).getBdStordocEntity();//发货仓库
                        BdCalbodyEntity bdCalbodyEntity1 = oldValue.get(0).getBdCalbodyEntity1();//收货库存组织
                        BdStordocEntity bdStordocEntity1 = oldValue.get(0).getBdStordocEntity1();//收货仓库
                        BdSalestruEntity bdSalestruEntity = oldValue.get(0).getBdSalestruEntity();//销售组织
                        BdDeptdocEntity bdDeptdocEntity = oldValue.get(0).getBdDeptdocEntity();//业务部门
                        BdCumandocEntity bdCumandocEntity = oldValue.get(0).getBdCumandocEntity();//客商管理档案
                        BdCubasdocEntity bdCubasdocEntity = oldValue.get(0).getBdCubasdocEntity();//客商基本档案
                        BdDefdocEntity platformArchives = oldValue.get(0).getPlatformArchives();//U8C平台档案
                        BdDefdocEntity shopArchives = oldValue.get(0).getShopArchives();//U8C店铺档案
                        String newState2 = oldValue.get(0).getNewState2();//交易成功-红 是否成功
                        String newState3 = oldValue.get(0).getNewState3();//交易成功-蓝 是否成功
                        SonDetailsDto sonDetailsDto = groupMergeDetailedRows(oldValue);//把汇总好的出库单明细行合并成一行
//                            BdInvmandocEntity bdInvmandocEntity = queryInventoryMan(sonDetailsDto, bdCalbodyEntity.getPkCorp());
                        BdInvmandocEntity bdInvmandocEntity = sonDetailsDto.getBdInvmandocEntity();//存货管理档案：取发货公司的存货管理档案
//                            BdInvbasdocEntity bdInvbasdocEntity = queryStockBasicArchives(bdInvmandocEntity.getPkInvmandoc(), deliverGoodsCorp.getPkCorp());
                        BdInvbasdocEntity bdInvbasdocEntity = sonDetailsDto.getBdInvbasdocEntity();//存货基础档案
//                            BdTaxitemsEntity bdTaxitemsEntity1 = queryBdTaxitems(bdInvbasdocEntity.getInvcode());
                        BdTaxitemsEntity bdTaxitemsEntity1 = sonDetailsDto.getBdTaxitemsEntity();//根据存货基础档案编码，查询当前存货的税率
                        BdRdclEntity bdRdclEntity = oldValue.get(0).getBdRdclEntity();//U8C收发类别

                        /**
                         * 先要确保红字销售订单生成后再生成蓝字销售订单,否则很有可能出现库存不足的问题，所以才共用了同一个summaryDimensionMap，
                         * 这样导致的问题是不好独立判断newState2、newState3的状态，独立判断这个状态有利于防止单据重新推送
                         */
                        logger.info("开始第一阶段：负数销售订单->(自动生成) 负数销售出库单");
                        Boolean isOneSuccess = false;
                        try {
                            //如果这个汇总集合，已经全部推送成功，那么就不需要推送红字销售订单，把isOneSuccess标识修改为true即可
                            if (!"Y".equals(newState2)) {
                                //验证数据完整性
//                            checkArchives(oldValue.get(0));
                                checkAllFail(oldValue, newState2, "1");
                                //取交易成功时间，生成业务日期
                                String generateBusinessDate = createGenerateBusinessDateTran(header);

                                SaleorderRequestDto saleorderRequestDto = new SaleorderRequestDto();
                                SaleorderRequestParentDto saleorderRequestParentDto = new SaleorderRequestParentDto();
                                saleorderRequestParentDto.setDbilldate(generateBusinessDate);//单据日期
                                saleorderRequestParentDto.setBretinvflag("Y");//退货标记
                                saleorderRequestParentDto.setCbiztype(bdBusitypeEntity.getPkBusitype());//业务流程
                                saleorderRequestParentDto.setCcalbodyid(bdCalbodyEntity.getPkCalbody());//库存组织
                                saleorderRequestParentDto.setCcustomerid(bdCumandocEntity.getPkCumandoc());//客户=开票单位=收货单位=表体收货单位=收货单位
                                saleorderRequestParentDto.setCdeptid(bdDeptdocEntity.getPkDeptdoc());//部门
                                saleorderRequestParentDto.setCemployeeid(null);//业务员
                                saleorderRequestParentDto.setCoperatorid(OverallConstant.getOverAllValue("u8cApiZdrPK"));//制单人
                                saleorderRequestParentDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//开票单位
                                saleorderRequestParentDto.setCreceiptcustomerid(bdCumandocEntity.getPkCumandoc());//收货单位
                                saleorderRequestParentDto.setCsalecorpid(bdSalestruEntity.getCsalestruid());//销售组织
                                saleorderRequestParentDto.setCwarehouseid(bdStordocEntity.getPkStordoc());//仓库
                                saleorderRequestParentDto.setDapprovedate(generateBusinessDate);//审核日期
                                saleorderRequestParentDto.setNdiscountrate("100.000000");//整单折扣
                                saleorderRequestParentDto.setPk_corp(bdCorpEntity.getPkCorp());//公司id
                                saleorderRequestParentDto.setVdef17(ProfilesActiveConstant.sourceSystem1);//来源系统
                                saleorderRequestParentDto.setVdef18(keyGroup);//汇总单号=汇总维度
//                            saleorderRequestParentDto.setVdef19(); 这两个值TOC传递不了的
//                            saleorderRequestParentDto.setVdef20();
                                saleorderRequestParentDto.setPk_defdoc2(platformArchives.getPkDefdoc());
                                saleorderRequestParentDto.setVdef2(platformArchives.getDocname());//平台，2024年8月8日 17:17:58 店铺档案自定义项1，先不传，后续维护好之后再传!
                                saleorderRequestParentDto.setPk_defdoc1(shopArchives.getPkDefdoc());
                                saleorderRequestParentDto.setVdef1(shopArchives.getDocname());//店铺
                                saleorderRequestParentDto.setPk_defdoc3(bdRdclEntity.getPkRdcl());//收发类别
                                saleorderRequestParentDto.setVdef3(bdRdclEntity.getRdname());
                                saleorderRequestDto.setParentvo(saleorderRequestParentDto);

                                List<SaleorderRequestChildrenDto> saleorderRequestChildrenDtoList = new ArrayList<>();
                                saleorderRequestDto.setChildrenvo(saleorderRequestChildrenDtoList);

                                String tax = "0." + new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString();
                                BigDecimal noriginalcurprice = null;//无税单价
                                BigDecimal noriginalcurmny = null;//无税金额
                                BigDecimal noriginalcurtaxprice = null;//含税单价
                                BigDecimal noriginalcursummny = null;//价税合计
                                BigDecimal noriginalcurtaxmny = null;//税额
                                try {
                                    noriginalcurtaxprice = sonDetailsDto.getGroupTotalPayAmount().divide(sonDetailsDto.getGroupShipQty(), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurprice = noriginalcurtaxprice.divide(new BigDecimal(1).add(new BigDecimal(tax)), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurmny = noriginalcurprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                    noriginalcursummny = noriginalcurtaxprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurtaxmny = noriginalcursummny.subtract(noriginalcurmny).setScale(2, BigDecimal.ROUND_HALF_UP);
                                } catch (Exception e) {
                                    logger.error("TOC金额计算错误", e);
                                    Assert.state(false, "金额计算错误，原因：{}" + e.getMessage());
                                }
                                //判断是否为赠品
                                Boolean isblargessflag = false;
                                if (noriginalcursummny.longValue() == 0) {
                                    isblargessflag = true;
                                }

                                SaleorderRequestChildrenDto saleorderRequestChildrenDto = new SaleorderRequestChildrenDto();
                                saleorderRequestChildrenDto.setBlargessflag(isblargessflag);//是否赠品
                                saleorderRequestChildrenDto.setCadvisecalbodyid(bdCalbodyEntity.getPkCalbody());//发货库存组织
                                saleorderRequestChildrenDto.setCbodywarehouseid(bdStordocEntity.getPkStordoc());//发货仓库
                                saleorderRequestChildrenDto.setCbodywarehousecode(bdStordocEntity.getStorcode());//发货仓库编码：这个字段不需要给openapi接口，而是提供给下游方法使用
                                saleorderRequestChildrenDto.setCconsigncorpid(deliverGoodsCorp.getPkCorp());//发货公司
                                saleorderRequestChildrenDto.setCcurrencytypeid("00010000000000000001");//币种
                                saleorderRequestChildrenDto.setCinventoryid(bdInvmandocEntity.getPkInvmandoc());//存货id
                                saleorderRequestChildrenDto.setCinventorycode(bdInvbasdocEntity.getInvcode());//存货编码
                                saleorderRequestChildrenDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//收货单位
                                saleorderRequestChildrenDto.setDconsigndate(generateBusinessDate);//计划发货日期
                                saleorderRequestChildrenDto.setDdeliverdate(generateBusinessDate);//要求收货日期
                                saleorderRequestChildrenDto.setNexchangeotobrate("1.00000000");//折本汇率
                                saleorderRequestChildrenDto.setNitemdiscountrate("100.000000");//单品折扣
                                saleorderRequestChildrenDto.setNnumber("-" + String.valueOf(sonDetailsDto.getGroupShipQty()));//数量
                                saleorderRequestChildrenDto.setNoriginalcurdiscountmny("0");//折扣额
                                saleorderRequestChildrenDto.setNoriginalcurmny("-" + noriginalcurmny.stripTrailingZeros().toPlainString());//无税金额
//                            saleorderRequestChildrenDto.setNoriginalcurnetprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税净价
//                            saleorderRequestChildrenDto.setNoriginalcurprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税单价
                                saleorderRequestChildrenDto.setNoriginalcursummny("-" + noriginalcursummny.stripTrailingZeros().toPlainString());//价税合计
                                saleorderRequestChildrenDto.setNoriginalcurtaxmny("-" + noriginalcurtaxmny.stripTrailingZeros().toPlainString());//税额
                                saleorderRequestChildrenDto.setNoriginalcurtaxnetprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税净价
                                saleorderRequestChildrenDto.setNoriginalcurtaxprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税单价
                                saleorderRequestChildrenDto.setNtaxrate(new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString());//税率
//                            saleorderRequestChildrenDto.setCreccalbodyid(bdCalbodyEntity1.getPkCalbody());//收货库存组织：2024年8月7日 16:21:48 和佳妮、道品一起测试，收货库存组织、收货仓库 是不需要传递的
//                            saleorderRequestChildrenDto.setCrecwareid(bdStordocEntity1.getPkStordoc());//收货仓库
                                saleorderRequestChildrenDtoList.add(saleorderRequestChildrenDto);

                                //销售订单单据推送到u8c
                                List<SaleorderRequestDto> saleorderRequestDtoList = new ArrayList<>();
                                saleorderRequestDtoList.add(saleorderRequestDto);

                                Map<String, List<SaleorderRequestDto>> stringStringMap = new HashMap<>();
                                stringStringMap.put("saleorder", saleorderRequestDtoList);
                                SoSaleResultRootDto soSaleResultRootDto = sendU8CTOCOrder(JSON.toJSONString(stringStringMap));

                                String vreceiptcode = null;
                                String pk_corp = null;
                                String csaleid = null;
                                if (soSaleResultRootDto != null && soSaleResultRootDto.getParentvo() != null) {
                                    SoSaleResultHeadDto parentvo = soSaleResultRootDto.getParentvo();
                                    vreceiptcode = parentvo.getVreceiptcode();
                                    pk_corp = parentvo.getPk_corp();
                                    csaleid = parentvo.getCsaleid();
                                } else {
                                    logger.error("第一阶段推送，令人匪夷所思的错误，正常来说是不可能执行到这里的，sendU8CTOCOrder方法的错误会向上抛出! json：{}", JSON.toJSON(soSaleResultRootDto));
                                }
                                logger.info("第一阶段：负数销售订单->(自动生成) 负数销售出库单抛出成功，销售订单编号：{} 销售订单主键：{} 销售公司：{}", vreceiptcode, csaleid, pk_corp);
                                isOneSuccess = true;
                                //第一阶段记录成功！
                                updateSuccessOrFail2(oldValue, "Y", "success", vreceiptcode, csaleid);
                            } else {
                                isOneSuccess = true;
                                logger.info("交易成功-红 业务日期：{} 汇总维度：{} 已经推送成功，不需要重新推送", header.getTradeSuccessAt(), keyGroup);
                            }
                        } catch (Exception e) {
                            logger.error("第一阶段：负数销售订单->(自动生成) 负数销售出库单抛出异常", e);
                            //第一阶段记录失败！
                            String message = e.getMessage();
                            if (message == null) {
                                message = "未知异常";
                            }
                            updateSuccessOrFail2(oldValue, "N", message, null, null);
                        }
                        logger.info("结束第一阶段：负数销售订单->(自动生成) 负数销售出库单");

                        if (isOneSuccess && !"Y".equals(newState3)) {
                            //2024年9月4日 14:30:31 第一阶段推送成功，才能执行第二阶段，否则不能执行以下代码
                            logger.info("开始第二阶段：销售订单 ->(自动生成) 销售出库单 ->(自动生成) 销售发票");
                            try {
                                //验证数据完整性
                                checkAllFail(oldValue, newState3, "2");
                                //取交易成功时间，生成业务日期
                                String generateBusinessDate = createGenerateBusinessDateTran(header);

                                SaleorderRequestDto saleorderRequestDto = new SaleorderRequestDto();
                                SaleorderRequestParentDto saleorderRequestParentDto = new SaleorderRequestParentDto();
                                saleorderRequestParentDto.setDbilldate(generateBusinessDate);//单据日期
                                saleorderRequestParentDto.setBretinvflag("N");//退货标记
                                saleorderRequestParentDto.setCbiztype(bdBusitypeEntity2.getPkBusitype());//业务流程
                                saleorderRequestParentDto.setCcalbodyid(bdCalbodyEntity.getPkCalbody());//库存组织
                                saleorderRequestParentDto.setCcustomerid(bdCumandocEntity.getPkCumandoc());//客户=开票单位=收货单位=表体收货单位=收货单位
                                saleorderRequestParentDto.setCdeptid(bdDeptdocEntity.getPkDeptdoc());//部门
                                saleorderRequestParentDto.setCemployeeid(null);//业务员
                                saleorderRequestParentDto.setCoperatorid(OverallConstant.getOverAllValue("u8cApiZdrPK"));//制单人
                                saleorderRequestParentDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//开票单位
                                saleorderRequestParentDto.setCreceiptcustomerid(bdCumandocEntity.getPkCumandoc());//收货单位
                                saleorderRequestParentDto.setCsalecorpid(bdSalestruEntity.getCsalestruid());//销售组织
                                saleorderRequestParentDto.setCwarehouseid(bdStordocEntity.getPkStordoc());//仓库
                                saleorderRequestParentDto.setDapprovedate(generateBusinessDate);//审核日期
                                saleorderRequestParentDto.setNdiscountrate("100.000000");//整单折扣
                                saleorderRequestParentDto.setPk_corp(bdCorpEntity.getPkCorp());//公司id
                                saleorderRequestParentDto.setVdef17(ProfilesActiveConstant.sourceSystem1);//来源系统
                                saleorderRequestParentDto.setVdef18(keyGroup);//汇总单号=汇总维度
                                saleorderRequestParentDto.setPk_defdoc2(platformArchives.getPkDefdoc());
                                saleorderRequestParentDto.setVdef2(platformArchives.getDocname());//平台，2024年8月8日 17:17:58 店铺档案自定义项1，先不传，后续维护好之后再传!
                                saleorderRequestParentDto.setPk_defdoc1(shopArchives.getPkDefdoc());
                                saleorderRequestParentDto.setVdef1(shopArchives.getDocname());//店铺
                                saleorderRequestParentDto.setPk_defdoc3(bdRdclEntity.getPkRdcl());//收发类别
                                saleorderRequestParentDto.setVdef3(bdRdclEntity.getRdname());
                                saleorderRequestDto.setParentvo(saleorderRequestParentDto);

                                List<SaleorderRequestChildrenDto> saleorderRequestChildrenDtoList = new ArrayList<>();
                                saleorderRequestDto.setChildrenvo(saleorderRequestChildrenDtoList);

                                String tax = "0." + new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString();
                                BigDecimal noriginalcurprice = null;//无税单价
                                BigDecimal noriginalcurmny = null;//无税金额
                                BigDecimal noriginalcurtaxprice = null;//含税单价
                                BigDecimal noriginalcursummny = null;//价税合计
                                BigDecimal noriginalcurtaxmny = null;//税额
                                try {
                                    noriginalcurtaxprice = sonDetailsDto.getGroupTotalPayAmount().divide(sonDetailsDto.getGroupShipQty(), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurprice = noriginalcurtaxprice.divide(new BigDecimal(1).add(new BigDecimal(tax)), 20, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurmny = noriginalcurprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                    noriginalcursummny = noriginalcurtaxprice.multiply(sonDetailsDto.getGroupShipQty()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                    noriginalcurtaxmny = noriginalcursummny.subtract(noriginalcurmny).setScale(2, BigDecimal.ROUND_HALF_UP);
                                } catch (Exception e) {
                                    logger.error("TOC金额计算错误", e);
                                    Assert.state(false, "金额计算错误，原因：{}" + e.getMessage());
                                }
                                //判断是否为赠品
                                Boolean isblargessflag = false;
                                if (noriginalcursummny.longValue() == 0) {
                                    isblargessflag = true;
                                }

                                SaleorderRequestChildrenDto saleorderRequestChildrenDto = new SaleorderRequestChildrenDto();
                                saleorderRequestChildrenDto.setBlargessflag(isblargessflag);//是否赠品
                                saleorderRequestChildrenDto.setCadvisecalbodyid(bdCalbodyEntity.getPkCalbody());//发货库存组织
                                saleorderRequestChildrenDto.setCbodywarehouseid(bdStordocEntity.getPkStordoc());//发货仓库
                                saleorderRequestChildrenDto.setCbodywarehousecode(bdStordocEntity.getStorcode());//发货仓库编码：这个字段不需要给openapi接口，而是提供给下游方法使用
                                saleorderRequestChildrenDto.setCconsigncorpid(deliverGoodsCorp.getPkCorp());//发货公司
                                saleorderRequestChildrenDto.setCcurrencytypeid("00010000000000000001");//币种
                                saleorderRequestChildrenDto.setCinventoryid(bdInvmandocEntity.getPkInvmandoc());//存货id
                                saleorderRequestChildrenDto.setCinventorycode(bdInvbasdocEntity.getInvcode());//存货编码
                                saleorderRequestChildrenDto.setCreceiptcorpid(bdCumandocEntity.getPkCumandoc());//收货单位
                                saleorderRequestChildrenDto.setDconsigndate(generateBusinessDate);//计划发货日期
                                saleorderRequestChildrenDto.setDdeliverdate(generateBusinessDate);//要求收货日期
                                saleorderRequestChildrenDto.setNexchangeotobrate("1.00000000");//折本汇率
                                saleorderRequestChildrenDto.setNitemdiscountrate("100.000000");//单品折扣
                                saleorderRequestChildrenDto.setNnumber(sonDetailsDto.getGroupShipQty().stripTrailingZeros().toPlainString());//数量
                                saleorderRequestChildrenDto.setNoriginalcurdiscountmny("0");//折扣额
                                saleorderRequestChildrenDto.setNoriginalcurmny(noriginalcurmny.stripTrailingZeros().toPlainString());//无税金额
//                            saleorderRequestChildrenDto.setNoriginalcurnetprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税净价
//                            saleorderRequestChildrenDto.setNoriginalcurprice(noriginalcurprice.stripTrailingZeros().toPlainString());//无税单价
                                saleorderRequestChildrenDto.setNoriginalcursummny(noriginalcursummny.stripTrailingZeros().toPlainString());//价税合计
                                saleorderRequestChildrenDto.setNoriginalcurtaxmny(noriginalcurtaxmny.stripTrailingZeros().toPlainString());//税额
                                saleorderRequestChildrenDto.setNoriginalcurtaxnetprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税净价
                                saleorderRequestChildrenDto.setNoriginalcurtaxprice(noriginalcurtaxprice.stripTrailingZeros().toPlainString());//含税单价
                                saleorderRequestChildrenDto.setNtaxrate(new BigDecimal(bdTaxitemsEntity1.getTaxratio()).stripTrailingZeros().toPlainString());//税率
//                            saleorderRequestChildrenDto.setCreccalbodyid(bdCalbodyEntity1.getPkCalbody());//收货库存组织：2024年8月7日 16:21:48 和佳妮、道品一起测试，收货库存组织、收货仓库 是不需要传递的
//                            saleorderRequestChildrenDto.setCrecwareid(bdStordocEntity1.getPkStordoc());//收货仓库
                                saleorderRequestChildrenDtoList.add(saleorderRequestChildrenDto);

                                //销售订单单据推送到u8c
                                List<SaleorderRequestDto> saleorderRequestDtoList = new ArrayList<>();
                                saleorderRequestDtoList.add(saleorderRequestDto);

                                Map<String, List<SaleorderRequestDto>> stringStringMap = new HashMap<>();
                                stringStringMap.put("saleorder", saleorderRequestDtoList);
                                SoSaleResultRootDto soSaleResultRootDto = sendU8CTOCOrder(JSON.toJSONString(stringStringMap));

                                String vreceiptcode = null;
                                String pk_corp = null;
                                String csaleid = null;
                                if (soSaleResultRootDto != null && soSaleResultRootDto.getParentvo() != null) {
                                    SoSaleResultHeadDto parentvo = soSaleResultRootDto.getParentvo();
                                    vreceiptcode = parentvo.getVreceiptcode();
                                    pk_corp = parentvo.getPk_corp();
                                    csaleid = parentvo.getCsaleid();
                                } else {
                                    logger.error("第二阶段推送，令人匪夷所思的错误，正常来说是不可能执行到这里的，sendU8CTOCOrder方法的错误会向上抛出! json：{}", JSON.toJSON(soSaleResultRootDto));
                                }
                                logger.info("第二阶段：负数销售订单->(自动生成) 负数销售出库单抛出成功，销售订单编号：{} 销售订单主键：{} 销售公司：{}", vreceiptcode, csaleid, pk_corp);
                                //第二阶段记录成功
                                updateSuccessOrFail3(oldValue, "Y", "success", vreceiptcode, csaleid);
                            } catch (Exception e) {
                                logger.error("第二阶段：销售订单 ->(自动生成) 销售出库单 ->(自动生成) 销售发票失败", e);
                                String message = e.getMessage();
                                if (message == null) {
                                    message = "未知错误";
                                }
                                //第二阶段记录失败
                                updateSuccessOrFail3(oldValue, "N", message, null, null);
                            }
                            logger.info("结束第二阶段：销售订单 ->(自动生成) 销售出库单 ->(自动生成) 销售发票");
                        } else {
                            logger.info("交易成功-蓝 业务日期：{} 汇总维度：{}", header.getTradeSuccessAt(), keyGroup);
                        }
                    }
                } else {
                    //2024年8月6日 11:28:54此处不记录失败，不认为是错误
                    logger.info("条件：bdBusitypeEntity != null && bdBusitypeEntity2 != null && summaryDimensionMap != null 条件不合法，因此主要的推送逻辑不会被执行！");
                }
            } catch (Exception e) {
                logger.error("外层转换逻辑抛出异常", e);
                // 记录失败
            }
        } else {
            logger.error("确认收入部分，没有需要推送到U8C的数据行！");
        }
    }

    /**
     * 批量修改成功、或者失败，适合档案查询的部分
     *
     * @author liuyang
     */
    private void updateFailOrSuccessTocofsSaleoutDetailedArchiveInquiry(List<ErrorHeaderDetailsDtoDto> errorHeaderDetailsDtoDtoList) {
        Assert.notNull(errorHeaderDetailsDtoDtoList, "errorHeaderDetailsDtoDtoList不能为空！");

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (errorHeaderDetailsDtoDtoList != null && errorHeaderDetailsDtoDtoList.size() > 0) {
                        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = new ArrayList<>();
                        for (int i = 0; i < errorHeaderDetailsDtoDtoList.size(); i++) {
                            ErrorHeaderDetailsDtoDto errorHeaderDetailsDtoDto = errorHeaderDetailsDtoDtoList.get(i);
                            HeaderDto header = errorHeaderDetailsDtoDto.getHeader();
                            List<DetailsDto> details = errorHeaderDetailsDtoDto.getDetails();
                            String newstate = errorHeaderDetailsDtoDto.getNewstate();
                            String newPushDate = errorHeaderDetailsDtoDto.getNewPushDate();
                            String newTransmitInfo = errorHeaderDetailsDtoDto.getNewTransmitInfo();

                            //如果报错内容太长了，则仅保留500个长度
                            if (newTransmitInfo != null && !"".equals(newTransmitInfo.trim()) && newTransmitInfo.length() >= 400) {
                                newTransmitInfo = newTransmitInfo.substring(0, 400);
                            }

                            for (int j = 0; j < details.size(); j++) {
                                DetailsDto detailsDto = details.get(j);

                                TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
                                tocofsSaleoutDetailedEntity.setId(detailsDto.getId());
                                tocofsSaleoutDetailedEntity.setNewpushdate(newPushDate);
                                tocofsSaleoutDetailedEntity.setNewtransmitinfo(newTransmitInfo);
                                tocofsSaleoutDetailedEntity.setNewstate(newstate);
                                tocofsSaleoutDetailedEntityList.add(tocofsSaleoutDetailedEntity);
                            }
                        }

                        //以50行为一个批次更新状态
                        if (tocofsSaleoutDetailedEntityList.size() > 0) {
                            List<List<TocofsSaleoutDetailedEntity>> splitListByCount = SplitListByCountUtil.splitListByCount(tocofsSaleoutDetailedEntityList, 50);
                            for (int i = 0; i < splitListByCount.size(); i++) {
                                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList1 = splitListByCount.get(i);
                                iTocofsSaleoutDetailedDao.entityInsertOrUpdateBatchStock1(tocofsSaleoutDetailedEntityList1);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("填充出库明细日志抛出异常", e);
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("updateFailOrSuccessTocofsSaleoutDetailedArchiveInquiry方法现场抛出异常", e);
        }
    }

    /**
     * 处理调用U8C接口，抛出的异常，或者调用成功的记录
     *
     * @author liuyang
     */
    private void updateSuccessOrFail1(List<SonDetailsDto> sonDetailsDtoList, String newstate, String newTransmitInfo, String newsystemnumber, String newsystemprimary) {
        if (newTransmitInfo != null && !"".equals(newTransmitInfo.trim()) && newTransmitInfo.length() >= 400) {
            newTransmitInfo = newTransmitInfo.substring(0, 400);
        }

        String finalNewTransmitInfo = newTransmitInfo;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String successY = "Y";
                    if (sonDetailsDtoList != null && sonDetailsDtoList.size() > 0) {
                        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = new ArrayList<>();
                        for (int i = 0; i < sonDetailsDtoList.size(); i++) {
                            SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(i);
                            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
                            tocofsSaleoutDetailedEntity.setId(sonDetailsDto.getId());
                            tocofsSaleoutDetailedEntity.setNewpushdate(getNewDateStr());
                            tocofsSaleoutDetailedEntity.setNewtransmitinfo(finalNewTransmitInfo);
                            tocofsSaleoutDetailedEntity.setNewstate(newstate);
                            if (successY.equals(newstate)) {
                                tocofsSaleoutDetailedEntity.setNewsystemnumber(newsystemnumber);
                                tocofsSaleoutDetailedEntity.setNewsystemprimary(newsystemprimary);
                            }
                            tocofsSaleoutDetailedEntityList.add(tocofsSaleoutDetailedEntity);
                        }

                        //以50行为一个批次，推送到Mysql
                        if (tocofsSaleoutDetailedEntityList.size() > 0) {
                            List<List<TocofsSaleoutDetailedEntity>> splitListByCount = SplitListByCountUtil.splitListByCount(tocofsSaleoutDetailedEntityList, 50);
                            for (int i = 0; i < splitListByCount.size(); i++) {
                                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList1 = splitListByCount.get(i);
                                iTocofsSaleoutDetailedDao.entityInsertOrUpdateBatchStock2(tocofsSaleoutDetailedEntityList1);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("处理调用U8C接口，抛出的异常，或者调用成功的记录对应的方法抛出异常", e);
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("updateSuccessOrFail1方法现场抛出异常", e);
        }
    }

    /**
     * 处理调用U8C接口，抛出的异常，或者调用成功的记录
     *
     * @author liuyang
     */
    private void updateSuccessOrFail2(List<SonDetailsDto> sonDetailsDtoList, String newstate, String newTransmitInfo, String newsystemnumber, String newsystemprimary) {
        if (newTransmitInfo != null && !"".equals(newTransmitInfo.trim()) && newTransmitInfo.length() >= 400) {
            newTransmitInfo = newTransmitInfo.substring(0, 400);
        }

        String finalNewTransmitInfo = newTransmitInfo;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String successY = "Y";
                    if (sonDetailsDtoList != null && sonDetailsDtoList.size() > 0) {
                        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = new ArrayList<>();
                        for (int i = 0; i < sonDetailsDtoList.size(); i++) {
                            SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(i);
                            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
                            tocofsSaleoutDetailedEntity.setId(sonDetailsDto.getId());
                            tocofsSaleoutDetailedEntity.setDef1(getNewDateStr());
                            tocofsSaleoutDetailedEntity.setDef2(finalNewTransmitInfo);
                            tocofsSaleoutDetailedEntity.setNewstate2(newstate);
                            if (successY.equals(newstate)) {
                                tocofsSaleoutDetailedEntity.setNewsystemnumber2(newsystemnumber);
                                tocofsSaleoutDetailedEntity.setNewsystemprimary2(newsystemprimary);
                            }
                            tocofsSaleoutDetailedEntityList.add(tocofsSaleoutDetailedEntity);
                        }

                        //以50行为一个批次，推送到Mysql
                        if (tocofsSaleoutDetailedEntityList.size() > 0) {
                            List<List<TocofsSaleoutDetailedEntity>> splitListByCount = SplitListByCountUtil.splitListByCount(tocofsSaleoutDetailedEntityList, 50);
                            for (int i = 0; i < splitListByCount.size(); i++) {
                                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList1 = splitListByCount.get(i);
                                iTocofsSaleoutDetailedDao.entityInsertOrUpdateBatchStock3(tocofsSaleoutDetailedEntityList1);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("处理调用U8C接口，抛出的异常，或者调用成功的记录对应的方法抛出异常", e);
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("updateSuccessOrFail2方法抛出异常", e);
        }
    }

    /**
     * 处理调用U8C接口，抛出的异常，或者调用成功的记录
     *
     * @author liuyang
     */
    private void updateSuccessOrFail3(List<SonDetailsDto> sonDetailsDtoList, String newstate, String newTransmitInfo, String newsystemnumber, String newsystemprimary) {
        if (newTransmitInfo != null && !"".equals(newTransmitInfo.trim()) && newTransmitInfo.length() >= 400) {
            newTransmitInfo = newTransmitInfo.substring(0, 400);
        }

        String finalNewTransmitInfo = newTransmitInfo;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String successY = "Y";
                    if (sonDetailsDtoList != null && sonDetailsDtoList.size() > 0) {
                        List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList = new ArrayList<>();
                        for (int i = 0; i < sonDetailsDtoList.size(); i++) {
                            SonDetailsDto sonDetailsDto = sonDetailsDtoList.get(i);
                            TocofsSaleoutDetailedEntity tocofsSaleoutDetailedEntity = new TocofsSaleoutDetailedEntity();
                            tocofsSaleoutDetailedEntity.setId(sonDetailsDto.getId());
                            tocofsSaleoutDetailedEntity.setDef3(getNewDateStr());
                            tocofsSaleoutDetailedEntity.setDef4(finalNewTransmitInfo);
                            tocofsSaleoutDetailedEntity.setNewstate3(newstate);
                            if (successY.equals(newstate)) {
                                tocofsSaleoutDetailedEntity.setNewsystemnumber3(newsystemnumber);
                                tocofsSaleoutDetailedEntity.setNewsystemprimary3(newsystemprimary);
                            }
                            tocofsSaleoutDetailedEntityList.add(tocofsSaleoutDetailedEntity);
                        }

                        //以50行为一个批次，推送到Mysql
                        if (tocofsSaleoutDetailedEntityList.size() > 0) {
                            List<List<TocofsSaleoutDetailedEntity>> splitListByCount = SplitListByCountUtil.splitListByCount(tocofsSaleoutDetailedEntityList, 50);
                            for (int i = 0; i < splitListByCount.size(); i++) {
                                List<TocofsSaleoutDetailedEntity> tocofsSaleoutDetailedEntityList1 = splitListByCount.get(i);
                                iTocofsSaleoutDetailedDao.entityInsertOrUpdateBatchStock4(tocofsSaleoutDetailedEntityList1);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("updateSuccessOrFail3：处理调用U8C接口，抛出的异常，或者调用成功的记录对应的方法抛出异常", e);
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (Exception e) {
            logger.error("updateSuccessOrFail3方法抛出异常", e);
        }
    }

    /**
     * 生成当前日期
     *
     * @author liuyang
     */
    private String getNewDateStr() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return now.format(formatter);
    }

    /**
     * 判断是否全部失败、或者全部成功
     *
     * @author liuyang
     */
    private void checkAllFail(List<SonDetailsDto> oldValue, String newstate, String type) {
        if (oldValue != null && oldValue.size() > 0) {
            if (newstate == null || "".equals(newstate)) {
                newstate = "N";
            }
            for (int i = 0; i < oldValue.size(); i++) {
                SonDetailsDto sonDetailsDto = oldValue.get(i);
                String newstate2 = sonDetailsDto.getNewState2();
                String newState3 = sonDetailsDto.getNewState3();
                if (newstate2 == null) {
                    newstate2 = "N";
                }
                if (newState3 == null) {
                    newState3 = "N";
                }
                if (type.equals("1")) {//红
                    if (!newstate2.equals(newstate)) {
                        Assert.state(false, "业务逻辑错误，标识为：{} 出库明细主键为：{}的数据行存在异常！", newstate2, sonDetailsDto.getId());
                    }
                }
                if (type.equals("2")) {//蓝
                    if (!newState3.equals(newstate)) {
                        Assert.state(false, "业务逻辑错误，标识为：{} 出库明细主键为：{}的数据行存在异常！", newState3, sonDetailsDto.getId());
                    }
                }
            }
        }
    }

    /**
     * 计算时间间隔
     *
     * @author liuyang
     */
    public String computingTime(String param) {
        if (param != null && !"".equals(param)) {
            String[] split = param.split("/");
            if (!(split.length == 2)) {
                Assert.state(false, "传递的日期格式不完整 格式参考：2024-04-01/2024-04-30");
            }

            LocalDate startDate = LocalDate.parse(split[0]);
            LocalDate endDate = LocalDate.parse(split[1]);

            List<String> stringArrayList = new ArrayList<>();
            List<String> dateRange = getDateRange(startDate, endDate);
            if (dateRange != null && dateRange.size() > 0) {
                for (int i = 0; i < dateRange.size(); i++) {
                    String dateStr = dateRange.get(i);
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(dateStr);
                    stringBuffer.append(" 00:00:00");
                    stringBuffer.append(",");
                    stringBuffer.append(dateStr);
                    stringBuffer.append(" 23:59:59");
                    stringArrayList.add(stringBuffer.toString());
                }
            }
            String collectDateStr = stringArrayList.stream().collect(Collectors.joining("*"));
            logger.info("类型：time_frame 生成的日期范围：" + collectDateStr);
            return collectDateStr;
        }
        return null;
    }

    private List<String> getDateRange(LocalDate startDate, LocalDate endDate) {
        List<String> dateRange = new ArrayList<>();
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            dateRange.add(currentDate.format(DateTimeFormatter.ISO_DATE));
            currentDate = currentDate.plusDays(1);
        }
        return dateRange;
    }

    /**
     * 计算全天时间段
     *
     * @author liuyang
     */
    public List<StartAndEndVo> calculateCalculateEntireDayPeriod(String dateStr) {
        List<StartAndEndVo> startAndEnd = new ArrayList<>();

        String calculateYesterdayStr = null;
        if (dateStr != null) {
            calculateYesterdayStr = dateStr;
        } else {
            calculateYesterdayStr = calculateYesterdayDate();//拉取'昨天'的日期
        }
        logger.info("OFS销售出库单同步U8C销售订单，目标拉取时间：" + calculateYesterdayStr);

        for (int i = 0; i <= 23; i++) {
            String iStr = null;
            if (i <= 9) {
                iStr = "0" + i;
            } else {
                iStr = String.valueOf(i);
            }
            String startTime = calculateYesterdayStr + " " + iStr + ":00:00";
            String endTime = calculateYesterdayStr + " " + iStr + ":59:59";

            StartAndEndVo startAndEndVo = new StartAndEndVo();
            startAndEndVo.setStart_time(startTime);
            startAndEndVo.setEnd_time(endTime);
            startAndEnd.add(startAndEndVo);
        }
        return startAndEnd;
    }

    /**
     * 计算昨天的单据日期，基于定时器在凌晨5分执行的情况下
     *
     * @author liuyang
     */
    public String calculateYesterdayDate() {
        DateTime yesterdayDate = DateUtil.yesterday();
        return DateUtil.format(yesterdayDate, "yyyy-MM-dd");
    }

    /**
     * 分割日期之后，再进行推送
     *
     * @author liuyang
     */
    public void splitDateAndPush(String param, String sceneType) throws Exception {
        try {
            Assert.notNull(param, "param不能为空!");
            Assert.state(!"".equals(param), "param不能为空！");

            Assert.notNull(sceneType, "sceneType不能为空！");
            Assert.state(!"".equals(sceneType), "sceneType不能为空！");

            if (param.contains("*")) {
                String[] params = param.split("\\*");
                if (params.length > 0) {
                    for (int i = 0; i < params.length; i++) {
                        String indexStr = params[i];
                        String[] split = indexStr.split(",");
                        logger.info("splitDateAndPush方法正在执行主要的逻辑 开始时间：{} 结束时间：{}", split[0], split[1]);
                        if (sceneType.equals(STOCK)) {
                            startImplementStockByTime(split[0], split[1]);
                        } else if (sceneType.equals(TRAN)) {
                            startImplementTranByTime(split[0], split[1]);
                        }
                    }
                }
            } else {
                String[] split = param.split(",");
                logger.info("splitDateAndPush方法正在执行主要的逻辑 开始时间：{} 结束时间：{}", split[0], split[1]);
                if (sceneType.equals(STOCK)) {
                    startImplementStockByTime(split[0], split[1]);
                } else if (sceneType.equals(TRAN)) {
                    startImplementTranByTime(split[0], split[1]);
                }
            }
        } catch (Exception e) {
            logger.error("记录splitDateAndPush方法抛出的异常", e);
        }
    }

    /**
     * 通过OFS销售出库单，联查OFS销售订单
     *
     * @param headerDetailsDtoList OFS销售出库单
     */
    private List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto> queryOfsOrder(List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> headerDetailsDtoList) throws Exception {
        List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto> allHeaderDetailsDtoArrayList = new ArrayList<>();
        try {
            if (headerDetailsDtoList != null && headerDetailsDtoList.size() > 0) {
                List<List<HeaderDetailsDto>> splitListByCount = SplitListByCountUtil.splitListByCount(headerDetailsDtoList, 100);
                for (int i = 0; i < splitListByCount.size(); i++) {
                    List<HeaderDetailsDto> headerDetailsDtos = splitListByCount.get(i);

                    StringBuffer stringBuffer = new StringBuffer();
                    if (headerDetailsDtos != null && headerDetailsDtos.size() > 0) {
                        for (int j = 0; j < headerDetailsDtos.size(); j++) {
                            HeaderDetailsDto headerDetailsDto = headerDetailsDtos.get(j);
                            HeaderDto header = headerDetailsDto.getHeader();
//                List<DetailsDto> details = headerDetailsDto.getDetails();
//                stringBuffer.append("'");
                            stringBuffer.append(header.getRefOrderCode());
//                stringBuffer.append("'");
                            stringBuffer.append(",");
                        }
                    }
                    String substring = stringBuffer.substring(0, stringBuffer.length());

                    List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto> headerDetailsDtoArrayList = new ArrayList<>();
                    QueryOfsSoSaleOutVo queryOfsSoSaleOutVo = new QueryOfsSoSaleOutVo();
                    queryOfsSoSaleOutVo.setCode(substring);
                    ofsStandardUtil.getOfsSaleOrder(queryOfsSoSaleOutVo, headerDetailsDtoArrayList, 1L);
                    allHeaderDetailsDtoArrayList.addAll(headerDetailsDtoArrayList);
                }
            }
        } catch (Exception e) {
            logger.error("queryOfsOrder方法抛出异常", e);
        }
        return allHeaderDetailsDtoArrayList;
    }

    /**
     * 代码匹配销售订单
     *
     * @param ofsSaleOrder    ofs销售订单集合
     * @param ofsSaleOutOrder ofs销售出库单集合
     * @author liuyang
     */
    private void findMatchingOfsOrder(List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto> ofsSaleOrder, List<com.hzya.frame.ttxofs.dto.ofssaleorderoutsearch.HeaderDetailsDto> ofsSaleOutOrder) throws Exception {
        if (ofsSaleOrder != null && ofsSaleOutOrder != null && ofsSaleOrder.size() > 0 && ofsSaleOutOrder.size() > 0) {
            try {
                for (int i = 0; i < ofsSaleOutOrder.size(); i++) {
                    HeaderDetailsDto headerDetailsDto = ofsSaleOutOrder.get(i);
                    HeaderDto header = headerDetailsDto.getHeader();
                    List<DetailsDto> details = headerDetailsDto.getDetails();

                    String targetRefOrderCode = header.getRefOrderCode();
                    for (int j = 0; j < ofsSaleOrder.size(); j++) {
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDetailsDto headerDetailsDto1 = ofsSaleOrder.get(j);
                        com.hzya.frame.ttxofs.dto.ofssalesordersearch.HeaderDto header1 = headerDetailsDto1.getHeader();
                        List<com.hzya.frame.ttxofs.dto.ofssalesordersearch.DetailsDto> details1 = headerDetailsDto1.getDetails();
                        if (header1.getCode().equals(targetRefOrderCode)) {
                            header.setHeaderDetailsDto(headerDetailsDto1);
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("findMatchingOfsOrder方法抛出异常", e);
            }
        }
    }
}