package com.sckw.contract.service.operateService;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sckw.contract.api.model.dto.req.SalesReportGoodsQueryDto;
import com.sckw.contract.api.model.dto.req.TradeEntListQueryFeignDto;
import com.sckw.contract.api.model.dto.res.*;
import com.sckw.contract.api.model.vo.LogisticsEntDtoVO;
import com.sckw.contract.api.model.vo.LogisticsGoodsDto;
import com.sckw.contract.api.model.vo.TradeContractUnitDto;
import com.sckw.contract.dao.KwcContractTradeMapper;
import com.sckw.contract.model.dto.req.QueryListReqDto;
import com.sckw.contract.model.dto.res.QueryListResDto;
import com.sckw.contract.api.model.dto.res.TradeEntInfoResVo;
import com.sckw.contract.model.entity.*;
import com.sckw.contract.model.report.TradeListExport;
import com.sckw.contract.model.vo.req.*;
import com.sckw.contract.model.vo.res.*;
import com.sckw.contract.repository.*;
import com.sckw.contract.service.CommonBusinessService;
import com.sckw.contract.service.KwcContractTradeGoodsService;
import com.sckw.contract.service.KwcContractTradeTrackService;
import com.sckw.contract.service.KwcContractTradeUnitService;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.*;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.BaseResult;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.excel.utils.ExcelUtil;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.ContractSignCompletedParam;
import com.sckw.order.api.model.TradeOrderContractVo;
import com.sckw.payment.api.feign.PaymentFeignService;
import com.sckw.payment.api.model.feign.WalletPrepaidDto;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.UserInfo;
import com.sckw.system.api.feign.DataPermissionFeignService;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.RemoteUserService;
import com.sckw.system.api.model.dto.req.DataPermissionFilterReqDto;
import com.sckw.system.api.model.dto.res.DataPermissionDTO;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.EntTypeResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import com.sckw.transport.api.dubbo.TransportRemoteService;
import com.sckw.transport.api.model.vo.RWaybillSubOrderVo;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author PC
 * @description 针对表【kwc_contract_trade(交易合同（采购合同/销售合同）)】的数据库操作Service实现
 * @createDate 2023-07-13 13:36:19
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class KwcContractTradeService {


    @Autowired
    private KwcContractTradeMapper kwcContractTradeMapper;

    @Autowired
    private KwcContractTradeGoodsService kwcContractTradeGoodsService;

    @Autowired
    private KwcContractTradeTrackService kwcContractTradeTrackService;

    @Autowired
    private KwcContractTradeUnitService kwcContractTradeUnitService;

    @Autowired
    private CommonBusinessService commonBusinessService;

    private final KwcContractTradeGoodsRepository kwcContractTradeGoodsRepository;
    private final KwcContractTradeRepository kwcContractTradeRepository;
    private final KwcContractTradeUnitRepository kwcContractTradeUnitRepository;
    private final KwcContractTradeOrderRepository kwcContractTradeOrderRepository;
    private final KwcContractLogisticsUnitRepository kwcContractLogisticsUnitRepository;
    private final KwcContractLogisticsGoodsRepository kwcContractLogisticsGoodsRepository;
    private final KwcContractLogisticsRepository contractLogisticsRepository;
    private final KwcContractLogisticsScoreRepository contractLogisticsScoreRepository;
    private final DataPermissionFeignService dataPermissionFeignService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteUserService remoteUserService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private GoodsInfoService goodsInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private TradeOrderInfoService tradeOrderInfoService;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private TransportRemoteService transportRemoteService;
    @Autowired
    private PaymentFeignService paymentFeignService;

    /**
     * 销售合同
     */
    @Value(value = "${jumpUrl.saleSendContract}")
    private String saleSendContract;

    /**
     * 采购合同
     */
    @Value(value = "${jumpUrl.purchaseSendContract}")
    private String purchaseSendContract;

    /**
     * 托运合同
     */
    @Value(value = "${jumpUrl.consignmentSendContract}")
    private String consignmentSendContract;

    /**
     * 承运合同
     */
    @Value(value = "${jumpUrl.acceptanceSendContract}")
    private String acceptanceSendContract;

    /**
     * app销售合同
     */
    @Value(value = "${jumpUrl.appSaleSendContract}")
    private String appSaleSendContract;

    /**
     * app采购合同
     */
    @Value(value = "${jumpUrl.appPurchaseSendContract}")
    private String appPurchaseSendContract;

    /**
     * app托运合同
     */
    @Value(value = "${jumpUrl.appConsignmentSendContract}")
    private String appConsignmentSendContract;

    /**
     * app承运合同
     */
    @Value(value = "${jumpUrl.appAcceptanceSendContract}")
    private String appAcceptanceSendContract;

    /**
     * @return PageResult
     * @desc: 分页查询
     * @param: reqVo
     * @author: sky
     * @date 2023/7/17
     */
    public PageResult queryListByPage(QueryListReqVo reqVo) {

        QueryTradeReq queryTradeReq = new QueryTradeReq();
        queryTradeReq.setContractCode(reqVo.getContractCode());
        queryTradeReq.setContractName(reqVo.getContractName());
        queryTradeReq.setSupplementCode(reqVo.getSupplementCode());
        queryTradeReq.setPurchaseEntId(reqVo.getPurchaseEntId());
        queryTradeReq.setSupplyEntId(reqVo.getSupplyEntId());
        queryTradeReq.setDispatchWay(reqVo.getDispatchWay());
        queryTradeReq.setStatus(reqVo.getStatus());
        queryTradeReq.setPageNum(reqVo.getPageNum());
        queryTradeReq.setPageSize(reqVo.getPageSize());

        List<QueryListResVo> queryListResVoPageDataResult = queryTradeListByPage(queryTradeReq);

        long total = countQueryTradeListByPage(queryTradeReq);
        PageInfo<QueryListResVo> pageInfo = new PageInfo<>(queryListResVoPageDataResult);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(reqVo.getPageNum());
        pageInfo.setPageSize(reqVo.getPageSize());
        return PageHelperUtil.getPageResult(pageInfo);
    }


    /**
     * @param queryListResDtos 入参
     * @return QueryListResVo
     * @desc: 抽取公共部分
     * @author: czh
     * @date: 2023/7/18
     */
    private List<QueryListResVo> getQueryListResVos(List<QueryListResDto> queryListResDtos, Map<Long,
            List<KwcContractTradeGoods>> contractIdGoodsIdKeyAndGoodsMap, Map<String, KwcContractTradeUnit> contractUnitTypeKeyAndUnitMap) {
        Map<Long, UserCacheResDto> longUserCacheResDtoMap = new HashMap<>(8);
        List<Long> initiateByList = queryListResDtos.stream().map(QueryListResDto::getInitiateBy).toList();
        if (CollectionUtils.isNotEmpty(initiateByList)) {
            longUserCacheResDtoMap = remoteSystemService.queryUserCacheMapByIds(initiateByList);
        }

        List<QueryListResVo> list = new ArrayList<>();
        for (QueryListResDto queryListResDto : queryListResDtos) {
            QueryListResVo queryListResVo = new QueryListResVo();
            BeanUtils.copyProperties(queryListResDto, queryListResVo);


            if (Objects.nonNull(queryListResDto.getUnitType())) {
                queryListResVo.setProvideEntName(queryListResDto.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0 ? queryListResDto.getEntName() : queryListResDto.getTargetEntName());
                queryListResVo.setPurchaseEntName(queryListResDto.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0 ? queryListResDto.getTargetEntName() : queryListResDto.getEntName());
            }
            if (Objects.equals(queryListResDto.getUnitType(), EntTypeEnum.SUPPLIER.getCode())) {
                queryListResVo.setProvideEntId(String.valueOf(queryListResDto.getProvideEntId()));
            } else if (Objects.equals(queryListResDto.getUnitType(), EntTypeEnum.PURCHASER.getCode())) {
                queryListResVo.setPurchaseEntId(String.valueOf(queryListResDto.getPurchaseEntId()));
            }

            UserCacheResDto userCacheResDto = longUserCacheResDtoMap.get(queryListResDto.getInitiateBy());
            if (Objects.nonNull(userCacheResDto)) {
                queryListResVo.setInitiateName(userCacheResDto.getName());
                queryListResVo.setInitiateEntName(Objects.isNull(userCacheResDto.getEntInfo()) ? "" : userCacheResDto.getEntInfo().getFirmName());
            }
            if (MapUtils.isNotEmpty(contractUnitTypeKeyAndUnitMap)) {
                KwcContractTradeUnit kwcContractTradeUnit =
                        contractUnitTypeKeyAndUnitMap.getOrDefault(queryListResDto.getId() + "-" + EntTypeEnum.SUPPLIER.getCode()
                                , new KwcContractTradeUnit());
                KwcContractTradeUnit contractTradeUnit =
                        contractUnitTypeKeyAndUnitMap.getOrDefault(queryListResDto.getId() + "-" + EntTypeEnum.PURCHASER.getCode()
                                , new KwcContractTradeUnit());
                queryListResVo.setProvideEntId(String.valueOf(kwcContractTradeUnit.getEntId()));
                queryListResVo.setPurchaseEntId(String.valueOf(contractTradeUnit.getEntId()));
                queryListResVo.setProvideEntName(kwcContractTradeUnit.getFirmName());
                queryListResVo.setPurchaseEntName(contractTradeUnit.getFirmName());
            }

            queryListResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(queryListResDto.getTrading())));
            queryListResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(queryListResDto.getStatus())).getName());
            queryListResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_TYPE.getType(), queryListResDto.getSigningWay()));
            queryListResVo.setSigningWay(String.valueOf(queryListResDto.getSigningWay()));
            queryListResVo.setUnloadWay(String.valueOf(queryListResDto.getUnloadWay()));
            queryListResVo.setUnloadWayName(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),
                    String.valueOf(queryListResDto.getUnloadWay())));
            queryListResVo.setAmount(queryListResDto.getAmount());
            queryListResVo.setPerformedAmount(queryListResDto.getPerformedAmount());
            BigDecimal performedAmountMoney = BigDecimal.ZERO;
            if (MapUtils.isNotEmpty(contractIdGoodsIdKeyAndGoodsMap)) {
                List<KwcContractTradeGoods> contractTradeGoods = contractIdGoodsIdKeyAndGoodsMap.get(queryListResDto.getId());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(contractTradeGoods)) {
                    for (KwcContractTradeGoods goods : contractTradeGoods) {
                        BigDecimal performedAmount = goods.getPerformedAmount() != null ? goods.getPerformedAmount() : BigDecimal.ZERO;
                        BigDecimal price = goods.getPrice() != null ? goods.getPrice() : BigDecimal.ZERO;
                        performedAmountMoney = performedAmountMoney.add(performedAmount.multiply(price));
                    }
                }
            }
            queryListResVo.setPerformedAmountMoney(performedAmountMoney);
            if (Objects.nonNull(queryListResVo.getEndTime())) {
                queryListResVo.setEndTime(DateUtils.getStartOfDay(queryListResVo.getEndTime()));
                String endDate = DateUtils.format(queryListResVo.getEndTime(), DateUtils.DATE_PATTERN);
                if (org.apache.commons.lang3.StringUtils.equals(endDate, "9999-12-30")) {
                    queryListResVo.setEndTime(null);
                }
            }
            list.add(queryListResVo);
        }
        return list;
    }

    @Transactional(rollbackFor = {})
    public Long addTradeContract(ContractTradeReqVo reqVo) {
        TradeBaseInfoReqVo baseInfo = reqVo.getBaseInfo();
        List<TradeGoodsInfoReqVo> goodsInfoList = reqVo.getGoodsInfo();
        //校验
        checkParam(baseInfo, goodsInfoList);

        Long id = reqVo.getId();
        //不为空时是修改
        if (Objects.nonNull(id)) {
            update(reqVo);
            return id;
        }

        //创建合同
        KwcContractTrade kwcContractTrade = getKwcContractTrade(baseInfo, reqVo.getGoodsInfo(), reqVo.getRemark(), reqVo.getPid());
        long contactId = new IdWorker(1L).nextId();
        kwcContractTrade.setId(contactId);
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(LoginUserHolder.getEntId());
        if (Objects.nonNull(entCacheResDto) && StringUtils.isNotBlank(entCacheResDto.getEntTypes())) {
            if (org.apache.commons.lang3.StringUtils.equals(entCacheResDto.getEntTypes(), String.valueOf(EntTypeEnum.SUPPLIER.getCode()))) {
                kwcContractTrade.setStatus(ContractStatusEnum.WAIT_APPROVE.getCode());
            } else if (org.apache.commons.lang3.StringUtils.equals(entCacheResDto.getEntTypes(), String.valueOf(EntTypeEnum.PURCHASER.getCode()))) {
                kwcContractTrade.setStatus(ContractStatusEnum.SUBMIT.getCode());
            }
        }

        kwcContractTrade.setSigningUrl(reqVo.getContractFile());
        if (kwcContractTradeMapper.insert(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }

        //保存交易合同商品信息
        kwcContractTradeGoodsService.saveContractTradeGoods(contactId, goodsInfoList, baseInfo.getStartTime(), baseInfo.getEndTime());

        //存单位信息
        kwcContractTradeUnitService.saveContractTradeUnit(contactId, baseInfo);
        return contactId;
    }

    private String changeFile(String contractFile) {
        if (StringUtils.isNotBlank(contractFile)) {
            JSONArray jsonArray = JSONArray.parseArray(contractFile);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.replaceAll(url));
            }
            return JSON.toJSONString(jsonArray);
        }
        return null;
    }


    private void checkParam(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo) {
        if (Objects.nonNull(baseInfo)) {
//            if (StringUtils.isNotBlank(baseInfo.getContractCode()) && baseInfo.getContractCode().length() > 20) {
//                throw new SystemException("合同编号超长！");
//            }
//
//            if (StringUtils.isNotBlank(baseInfo.getContractName()) && baseInfo.getContractName().length() > 20) {
//                throw new SystemException("合同名称超长！");
//            }
            //按卸货筽量时必选计量方式
            if (Objects.equals(baseInfo.getUnloadWay(), Integer.parseInt(DictEnum.LOAD_UNLOAD_WAY_2.getValue())) && Objects.isNull(baseInfo.getMeasurementWay())) {
                throw new SystemException("卸货方式为按卸货筽量时，计量方式不能为空！");
            }
            if (Objects.equals(baseInfo.getSettlement(), 1)) {
                throw new SystemException("暂不支持普通结算模式！");
            }
        }

        if (CollectionUtils.isNotEmpty(goodsInfo)) {

            boolean b = hasDuplicateGoodsId(goodsInfo);
            if (b) {
                throw new SystemException("商品不能重复！");
            }
            for (TradeGoodsInfoReqVo goodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(goodsInfoReqVo.getPrice()) && !RegularUtils.matchNumberWithFix(goodsInfoReqVo.getPrice().toString(), 10, 2)) {
                    throw new SystemException("单价超长！");
                }

                if (Objects.nonNull(goodsInfoReqVo.getAmount()) && !RegularUtils.matchNumberWithFix(goodsInfoReqVo.getAmount().toString(), 10, 2)) {
                    throw new SystemException("采购数量超长！");
                }
            }
            //验证供应单位必须在贸易合同生效期内,且有包含该商品的自动派车的物流合同
            checkLogContractTime(baseInfo, goodsInfo);
        }
        if (Objects.equals(DispatchWayEnums.MANUAL_DISPATCH.getCode(), baseInfo.getDispatchWay())) {
            if (baseInfo.getConsignment() == null) {
                throw new SystemException("派车方式为手动派单时，托运方式不能为空！");
            }
        }
        KwcContractTrade kwcContractTrade = kwcContractTradeRepository.queryByContractNo(baseInfo.getContractCode());
        if (Objects.nonNull(kwcContractTrade)) {
            throw new SystemException("合同编号已存在！");
        }
    }

    /**
     * 校验供应单位必须在贸易合同生效期内,且有包含该商品的自动派车的物流合同
     *
     * @param baseInfo
     * @param goodsInfo
     */
    private void checkLogContractTime(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo) {
        if (Objects.equals(DispatchWayEnums.AUTO_DISPATCH.getCode(), baseInfo.getDispatchWay())) {
            //商品ids
            List<Long> goodsIdList = goodsInfo.stream().map(TradeGoodsInfoReqVo::getGoodsId).collect(Collectors.toList());
            //查询满足条件的物流合同
            List<LogisticsEntDtoVO> logisticsList = queryAutoContractLogOrder(baseInfo.getProvideEntId(), goodsIdList);
            if (CollectionUtils.isEmpty(logisticsList)) {
                throw new SystemException("请供应商先签订包含贸易商品的自动派车物流合同。");
            }
            //结束时间最早的
            LogisticsEntDtoVO logEndTimeMin = logisticsList.stream()
                    .filter(log -> log.getEndTime() != null)
                    .min(Comparator.comparing(LogisticsEntDtoVO::getEndTime))
                    .orElse(new LogisticsEntDtoVO());
            log.error("自动派车物流合同将在【{}】失效，将影响派车，请及时续签。", logEndTimeMin.getEndTime());
        }
    }

    private static boolean hasDuplicateGoodsId(List<TradeGoodsInfoReqVo> goodsInfo) {
        if (goodsInfo == null || goodsInfo.isEmpty()) {
            return false;
        }

        Set<Long> goodsIdSet = new HashSet<>();
        for (TradeGoodsInfoReqVo info : goodsInfo) {
            if (info.getGoodsId() != null) {
                if (!goodsIdSet.add(info.getGoodsId())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @param baseInfo 贸易基本信息 remark备注  pid父id
     * @return KwcContractTrade
     * @desc: 抽取公共
     * @author: czh
     * @date: 2023/7/20
     */
    public KwcContractTrade getKwcContractTrade(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo, String remark, Long pid) {
        Date date = new Date();
        KwcContractTrade kwcContractTrade = new KwcContractTrade();
        kwcContractTrade.setEntId(LoginUserHolder.getEntId());
        kwcContractTrade.setContractNo(baseInfo.getContractCode());
        kwcContractTrade.setName(baseInfo.getContractName());
        kwcContractTrade.setSigningWay(baseInfo.getSigningWay());
        kwcContractTrade.setTrading(baseInfo.getTrading());
        kwcContractTrade.setStartTime(baseInfo.getStartTime());
        if (Objects.nonNull(baseInfo.getEndTime())) {
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(baseInfo.getEndTime()));
        } else {
            LocalDate localDate = LocalDate.of(9999, 12, 30);
            Date date1 = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(date1));
        }
        kwcContractTrade.setPerformedAmount(new BigDecimal("0"));
        kwcContractTrade.setContractPid(pid);
        kwcContractTrade.setRemark(remark);
        kwcContractTrade.setCreateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setCreateTime(date);
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setDelFlag(Global.NO);

        kwcContractTrade.setSettlement(baseInfo.getSettlement());
        kwcContractTrade.setConsignment(baseInfo.getConsignment());
        kwcContractTrade.setUnloadWay(baseInfo.getUnloadWay());
        kwcContractTrade.setSalesmanId(baseInfo.getSalesmanId());
        kwcContractTrade.setSalesmanPhone(baseInfo.getSalesmanPhone());
        kwcContractTrade.setDispatchWay(baseInfo.getDispatchWay());


        BigDecimal amountTotal = new BigDecimal(Global.NUMERICAL_ZERO);
        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (TradeGoodsInfoReqVo tradeGoodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(tradeGoodsInfoReqVo.getAmount())) {
                    amountTotal = amountTotal.add(tradeGoodsInfoReqVo.getAmount());
                }
            }
        }
        kwcContractTrade.setAmount(amountTotal);
        kwcContractTrade.setMeasurementWay(baseInfo.getMeasurementWay());
        return kwcContractTrade;
    }

    /**
     * @param reqVo 补充入参
     * @desc: 补充合同
     * @author: czh
     * @date: 2023/7/14
     */
    public void supplement(ContractTradeReqVo reqVo) {
        Long id = reqVo.getPid();
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }

        submit(reqVo);
//        addTradeContract(reqVo);
    }


    /**
     * @param id 合同id
     * @return ContractTradeDetailResVo
     * @desc: 合同详情
     * @author: czh
     * @date 2023/7/16
     */
    public ContractTradeDetailResVo detail(Long id) {
        //基础信息
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (Objects.isNull(kwcContractTrade)) {
            return null;
        }

        return buildContractTradeDetailResVo(kwcContractTrade);
    }


    /**
     * @param kwcContractTrade 合同实体
     * @return ContractTradeDetailResVo
     * @desc: 构建返参
     * @author: czh
     * @date: 2023/7/20
     */
    private ContractTradeDetailResVo buildContractTradeDetailResVo(KwcContractTrade kwcContractTrade) {
        Long id = kwcContractTrade.getId();
        TradeBaseInfoResVo tradeBaseInfoResVo = new TradeBaseInfoResVo();
        tradeBaseInfoResVo.setContractCode(kwcContractTrade.getContractNo());
        tradeBaseInfoResVo.setContractName(kwcContractTrade.getName());
        tradeBaseInfoResVo.setEndTime(Objects.isNull(kwcContractTrade.getEndTime()) ? Global.EMPTY_STRING : DateUtils.format(kwcContractTrade.getEndTime()));
        tradeBaseInfoResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_WAY.getType(), String.valueOf(kwcContractTrade.getSigningWay())));
        tradeBaseInfoResVo.setSigningWay(StringUtils.objectStr(kwcContractTrade.getSigningWay()));
        tradeBaseInfoResVo.setStartTime(kwcContractTrade.getStartTime());
        tradeBaseInfoResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(kwcContractTrade.getTrading())));
        tradeBaseInfoResVo.setTrading(StringUtils.objectStr(kwcContractTrade.getTrading()));
        tradeBaseInfoResVo.setAmount(kwcContractTrade.getAmount());
        tradeBaseInfoResVo.setPerformedAmount(kwcContractTrade.getPerformedAmount());

        ContractTradeDetailResVo contractTradeDetailResVo = new ContractTradeDetailResVo();
        contractTradeDetailResVo.setStatus(kwcContractTrade.getStatus());
        contractTradeDetailResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(kwcContractTrade.getStatus())).getName());
        contractTradeDetailResVo.setRemark(kwcContractTrade.getRemark());


        List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(id);
        if (CollectionUtils.isNotEmpty(kwcContractTradeUnits)) {
            for (KwcContractTradeUnit kwcContractTradeUnit : kwcContractTradeUnits) {
                if (kwcContractTradeUnit.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0) {
                    tradeBaseInfoResVo.setProvideEntName(kwcContractTradeUnit.getFirmName());
                    tradeBaseInfoResVo.setProvidePhone(kwcContractTradeUnit.getSignPhone());
                    tradeBaseInfoResVo.setProvideContacts(kwcContractTradeUnit.getContacts());
                    tradeBaseInfoResVo.setProvideEntId(kwcContractTradeUnit.getEntId());
                }

                if (kwcContractTradeUnit.getUnitType().compareTo(EntTypeEnum.PURCHASER.getCode()) == 0) {
                    tradeBaseInfoResVo.setPurchaseEntName(kwcContractTradeUnit.getFirmName());
                    tradeBaseInfoResVo.setPurchasePhone(kwcContractTradeUnit.getSignPhone());
                    tradeBaseInfoResVo.setPurchaseContacts(kwcContractTradeUnit.getContacts());
                    tradeBaseInfoResVo.setPurchaseEntId(kwcContractTradeUnit.getEntId());
                }
            }
        }
        contractTradeDetailResVo.setBaseInfo(tradeBaseInfoResVo);
        contractTradeDetailResVo.setId(id);

        //标的信息
        List<KwcContractTradeGoods> kwcContractTradeGoodsList = kwcContractTradeGoodsService.queryGoodsInfoByContractId(id);
        Map<Long, KwpGoods> goodsMap = new HashMap<>(8);
        if (CollectionUtils.isNotEmpty(kwcContractTradeGoodsList)) {
            List<TradeGoodsInfoResVo> tradeGoodsInfoResVoList = new ArrayList<>();
            List<Long> goodsIdList = kwcContractTradeGoodsList.stream().map(KwcContractTradeGoods::getGoodsId).toList();
            goodsMap = goodsInfoService.getGoodsByIds(goodsIdList);
            StringBuilder keys = new StringBuilder();
            for (KwcContractTradeGoods item : kwcContractTradeGoodsList) {
                keys.append(DictTypeEnum.UNIT_TYPE.getType()).append(Global.POUND).append(item.getUnit()).append(Global.COMMA);
            }
            Map<String, SysDictResDto> stringSysDictResDtoMap = remoteSystemService.queryDictMapByTypeValues(keys.toString());

            for (KwcContractTradeGoods kwcContractTradeGoods : kwcContractTradeGoodsList) {
                TradeGoodsInfoResVo tradeGoodsInfoResVo = new TradeGoodsInfoResVo();
                tradeGoodsInfoResVo.setAmount(kwcContractTradeGoods.getAmount());
                tradeGoodsInfoResVo.setPrice(kwcContractTradeGoods.getPrice());
                tradeGoodsInfoResVo.setUnit(kwcContractTradeGoods.getUnit());
                tradeGoodsInfoResVo.setGoodsId(kwcContractTradeGoods.getGoodsId());
                KwpGoods kwpGoods = goodsMap.get(kwcContractTradeGoods.getGoodsId());
                if (Objects.nonNull(kwpGoods)) {
                    tradeGoodsInfoResVo.setGoodsName(kwpGoods.getName());
                }

                SysDictResDto sysDictResDto = stringSysDictResDtoMap.get(DictTypeEnum.UNIT_TYPE.getType() + Global.POUND + kwcContractTradeGoods.getUnit());
                if (Objects.nonNull(sysDictResDto)) {
                    tradeGoodsInfoResVo.setUnitName(sysDictResDto.getLabel());
                }

                tradeGoodsInfoResVoList.add(tradeGoodsInfoResVo);
            }
            contractTradeDetailResVo.setGoodsInfo(tradeGoodsInfoResVoList);
        }

        //合同文件
        List<String> fileList = new ArrayList<>();
        String signedUrl = kwcContractTrade.getSignedUrl();
        if (StringUtils.isNotBlank(signedUrl)) {
            JSONArray jsonArray = JSONArray.parseArray(signedUrl);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.splice(url));
            }
            fileList.add(JSON.toJSONString(jsonArray));
        }

        String signingUrl = kwcContractTrade.getSigningUrl();
        if (StringUtils.isNotBlank(signingUrl)) {
            JSONArray jsonArray = JSONArray.parseArray(signingUrl);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.splice(url));
            }
            fileList.add(JSON.toJSONString(jsonArray));
        }

        contractTradeDetailResVo.setContractFile(fileList.stream().filter(StringUtils::isNotBlank).toList());

        //流程记录
        contractTradeDetailResVo.setTrackInfo(kwcContractTradeTrackService.queryContractTrackByContractId(kwcContractTrade.getId()));

        List<KwcContractTrade> supplementList = getSupplementList(id);
        if (CollectionUtils.isNotEmpty(supplementList)) {
            List<ContractTradeDetailResVo> child = new ArrayList<>();
            for (KwcContractTrade supplement : supplementList) {
                child.add(buildContractTradeDetailResVo(supplement));
            }
            contractTradeDetailResVo.setChild(child);
        }
        return contractTradeDetailResVo;
    }


    private List<KwcContractTrade> getSupplementList(Long id) {
        LambdaQueryWrapper<KwcContractTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwcContractTrade::getContractPid, id);
        wrapper.eq(KwcContractTrade::getDelFlag, Global.NO);
//        wrapper.eq(KwcContractTrade::getStatus, Global.NO);
        return kwcContractTradeMapper.selectList(wrapper);
    }


    /**
     * @param reqVo id
     * @desc: 发起签约
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public Long submit(ContractTradeReqVo reqVo) {
        Long id = reqVo.getId();
        if (Objects.isNull(id)) {
            //创建合同
            id = addTradeContract(reqVo);
            changeToSubmit(id);
            sign(reqVo, id);
            return id;
        }
        update(reqVo);
        changeToSubmit(id);
        sign(reqVo, id);
        return id;
    }

    /**
     * @param reqVo 入参 id合同id
     * @desc: 签约
     * @author: czh
     * @date: 2023/8/18
     */
    private void sign(ContractTradeReqVo reqVo, Long id) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (DictEnum.SIGNING_WAY_1.getValue().equals(String.valueOf(reqVo.getBaseInfo().getSigningWay()))) {
            commonBusinessService.postToEsign(reqVo.getBaseInfo().getProvidePhone(),
                    reqVo.getBaseInfo().getPurchasePhone(),
                    reqVo.getBaseInfo().getProvideEntId(),
                    reqVo.getBaseInfo().getPurchaseEntId(),
                    reqVo.getContractFile(),
                    id,
                    reqVo.getBaseInfo().getContractName());
            sendTradeMessage(kwcContractTrade);
        }

        //线下签约直接通过
        if (DictEnum.SIGNING_WAY_2.getValue().equals(String.valueOf(reqVo.getBaseInfo().getSigningWay()))) {
            ESignCallBackReqVo eSignCallBackReqVo = new ESignCallBackReqVo();
            eSignCallBackReqVo.setContractId(id);
            eSignCallBackReqVo.setStatus(ContractStatusEnum.SIGNED.getCode());
            //发送消息
            sendTradeMessage(kwcContractTrade);
            //审批通过
            commonBusinessService.approval(eSignCallBackReqVo);
        }
    }


    private void sendTradeMessage(KwcContractTrade kwcContractTrade) {
        try {
            List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(kwcContractTrade.getId());
            Map<Integer, KwcContractTradeUnit> collect = kwcContractTradeUnits.stream().collect(Collectors.toMap(KwcContractTradeUnit::getUnitType, Function.identity()));
            KwcContractTradeUnit kwcContractTradeUnit = collect.get(CooperateTypeEnum.PURCHASER.getCode());
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(kwcContractTradeUnit.getEntId());
            Map<String, Object> map = CollectionUtils.createHashMap();
            map.put("entName", entCacheResDto.getFirmName());
            map.put("contract_no", kwcContractTrade.getContractNo());
            map.put("name", kwcContractTrade.getName());
            MessageEnum messageEnum;
            if (Objects.nonNull(kwcContractTrade.getContractPid())) {
                messageEnum = MessageEnum.SAELCONTRACT_SUBMIT_DATA;
            } else {
                messageEnum = MessageEnum.SAELCONTRACT_SEND_CONTRACT;
            }
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(kwcContractTrade.getCreateBy()).setEntId(kwcContractTrade.getEntId())),
                    messageEnum,
                    map,
                    saleSendContract,
                    appSaleSendContract);


            if (Objects.nonNull(kwcContractTrade.getContractPid())) {
                messageEnum = MessageEnum.BUYCONTRACT_SUPPLYPROCESS_SEND;
            } else {
                messageEnum = MessageEnum.BUYCONTRACT_PROCESS_SEND;
            }

            EntCacheResDto entCacheResDto2 = remoteSystemService.queryEntTreeById(kwcContractTradeUnit.getEntId());
            KwcContractTradeUnit kwcContractTradeUnit2 = collect.get(CooperateTypeEnum.SUPPLIER.getCode());
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntCacheById(kwcContractTradeUnit2.getEntId());
            map.put("entName", entCacheResDto1.getFirmName());
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(entCacheResDto2.getContactsId()).setEntId(entCacheResDto2.getId())),
                    messageEnum,
                    map,
                    purchaseSendContract,
                    appPurchaseSendContract);
        } catch (Exception e) {
            log.error("合同签约流程已发起消息出错：", e);
        }
    }


    /**
     * @param id 合同id
     * @desc: 更新合同为发起
     * @author: czh
     * @date: 2023/7/20
     */
    private void changeToSubmit(Long id) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        int code = ContractStatusEnum.SUBMIT.getCode();
        kwcContractTrade.setStatus(code);
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
        kwcContractTradeTrackService.saveContractTradeTrack(id, code, new Date());
    }

    /**
     * @desc: 修改草稿
     * @param: reqVo 入参
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void update(ContractTradeReqVo reqVo) {
        Long contractId = reqVo.getId();
        Date date = new Date();
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(contractId);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }

        EntTypeResDto entTypeResDto = remoteSystemService.queryEntTypeById(LoginUserHolder.getEntId());

        TradeBaseInfoReqVo baseInfo = reqVo.getBaseInfo();
        if (Objects.equals(baseInfo.getUnloadWay(), Integer.parseInt(DictEnum.LOAD_UNLOAD_WAY_2.getValue())) && Objects.isNull(baseInfo.getMeasurementWay())) {
            throw new BusinessException("卸货方式为按卸货筽量时，计量方式不能为空！");
        }
        kwcContractTrade.setEntId(LoginUserHolder.getEntId());
        kwcContractTrade.setContractNo(baseInfo.getContractCode());
        kwcContractTrade.setName(baseInfo.getContractName());
        kwcContractTrade.setSigningWay(baseInfo.getSigningWay());
        kwcContractTrade.setTrading(baseInfo.getTrading());
        kwcContractTrade.setStartTime(baseInfo.getStartTime());
        kwcContractTrade.setEndTime(baseInfo.getEndTime());
        if (Objects.nonNull(baseInfo.getEndTime())) {
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(baseInfo.getEndTime()));
        }
        kwcContractTrade.setPerformedAmount(new BigDecimal("0"));
        kwcContractTrade.setContractPid(reqVo.getPid());
        kwcContractTrade.setRemark(reqVo.getRemark());

        kwcContractTrade.setSettlement(baseInfo.getSettlement());
        kwcContractTrade.setConsignment(baseInfo.getConsignment());
        kwcContractTrade.setUnloadWay(baseInfo.getUnloadWay());
        kwcContractTrade.setSalesmanId(baseInfo.getSalesmanId());
        kwcContractTrade.setSalesmanPhone(baseInfo.getSalesmanPhone());
        kwcContractTrade.setDispatchWay(baseInfo.getDispatchWay());
        List<TradeGoodsInfoReqVo> goodsInfo = reqVo.getGoodsInfo();
        BigDecimal amountTotal = new BigDecimal(Global.NUMERICAL_ZERO);
        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (TradeGoodsInfoReqVo tradeGoodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(tradeGoodsInfoReqVo.getAmount())) {
                    amountTotal = amountTotal.add(tradeGoodsInfoReqVo.getAmount());
                }
            }
        }
        if (Objects.nonNull(entTypeResDto) && Objects.equals(entTypeResDto.getType(), EntTypeEnum.SUPPLIER.getCode())) {
            kwcContractTrade.setStatus(ContractStatusEnum.WAIT_APPROVE.getCode());
        } else if (Objects.nonNull(entTypeResDto) && Objects.equals(entTypeResDto.getType(), EntTypeEnum.PURCHASER.getCode())) {
            kwcContractTrade.setStatus(ContractStatusEnum.SUBMIT.getCode());
        }
        kwcContractTrade.setAmount(amountTotal);
        kwcContractTrade.setSigningUrl(reqVo.getContractFile());
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setMeasurementWay(baseInfo.getMeasurementWay());
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }


        //保存交易合同商品信息-先把以前的删除
        List<KwcContractTradeGoods> kwcContractTradeGoodsList = kwcContractTradeGoodsService.queryGoodsInfoByContractId(contractId);
        if (CollectionUtils.isNotEmpty(kwcContractTradeGoodsList)) {
            kwcContractTradeGoodsList.forEach(item -> {
                item.setDelFlag(Global.YES);
                item.setUpdateBy(LoginUserHolder.getUserId());
                item.setUpdateTime(date);
            });

            if (kwcContractTradeGoodsService.updateBatch(kwcContractTradeGoodsList) != kwcContractTradeGoodsList.size()) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        }
        kwcContractTradeGoodsService.saveContractTradeGoods(kwcContractTrade.getId(), reqVo.getGoodsInfo(),
                baseInfo.getStartTime(), baseInfo.getEndTime());

        //保存单位信息-先把以前的删除
        List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(contractId);
        if (CollectionUtils.isNotEmpty(kwcContractTradeUnits)) {
            kwcContractTradeUnits.forEach(item -> {
                item.setDelFlag(Global.YES);
                item.setUpdateBy(LoginUserHolder.getUserId());
                item.setUpdateTime(date);
            });

            if (kwcContractTradeUnitService.updateBatch(kwcContractTradeUnits) != kwcContractTradeUnits.size()) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        }
        kwcContractTradeUnitService.saveContractTradeUnit(contractId, reqVo.getBaseInfo());
    }


    /**
     * @desc: 手动完结
     * @param: reqVo ids
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void complete(CompleteReqVo reqVo) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(reqVo.getId());
        if (!kwcContractTrade.getStatus().equals(ContractStatusEnum.SIGNED.getCode())) {
            throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_028);
        }
        kwcContractTrade.setStatus(ContractStatusEnum.COMPLETE.getCode());
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(new Date());
        kwcContractTrade.setPerformedAmount(reqVo.getPerformedAmount());
        kwcContractTrade.setRemark(reqVo.getRemark());
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
        kwcContractTradeTrackService.saveContractTradeTrack(kwcContractTrade.getId(), ContractTrackEnum.OVER.getCode(), new Date());

        //完结相关订单
        ContractSignCompletedParam contractSignCompletedParam = new ContractSignCompletedParam();
        contractSignCompletedParam.setContractId(kwcContractTrade.getContractPid());
        contractSignCompletedParam.setUpdateBy(LoginUserHolder.getUserId());
        contractSignCompletedParam.setUpdateByName(LoginUserHolder.getUserName());
        tradeOrderInfoService.contractSignCompleted(contractSignCompletedParam);

        //发送消息
        try {
            List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(kwcContractTrade.getId());
            Map<Integer, KwcContractTradeUnit> collect = kwcContractTradeUnits.stream().collect(Collectors.toMap(KwcContractTradeUnit::getUnitType, Function.identity()));
            KwcContractTradeUnit kwcContractTradeUnit = collect.get(CooperateTypeEnum.PURCHASER.getCode());
            Long entId = kwcContractTradeUnit.getEntId();
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(entId);
            Map<String, Object> map = CollectionUtils.createHashMap();
            map.put("entName", entCacheResDto.getFirmName());
            map.put("contract_no", kwcContractTrade.getContractNo());
            map.put("name", kwcContractTrade.getName());

            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(kwcContractTrade.getCreateBy()).setEntId(kwcContractTrade.getEntId())),
                    MessageEnum.SAELCONTRACT_COMPLETE_CONTRACT,
                    map,
                    saleSendContract,
                    appSaleSendContract);


            KwcContractTradeUnit kwcContractTradeUnit2 = collect.get(CooperateTypeEnum.SUPPLIER.getCode());
            Long entId1 = kwcContractTradeUnit2.getEntId();
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntCacheById(entId1);
            EntCacheResDto entCacheResDto2 = remoteSystemService.queryEntTreeById(entId);
            map.put("entName", entCacheResDto1.getFirmName());
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(entCacheResDto2.getContactsId()).setEntId(entCacheResDto2.getId())),
                    MessageEnum.BUYCONTRACT_COMPLETE_CONTRACT,
                    map,
                    purchaseSendContract,
                    appPurchaseSendContract);
        } catch (Exception e) {
            log.error("完结合同消息出错:", e);
        }
    }


    /**
     * @desc: 手动完结
     * @param: reqVo ids
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void delete(String ids) {
        List<Long> contractIdList = Arrays.stream(ids.split(Global.COMMA)).map(Long::parseLong).toList();
        List<KwcContractTrade> kwcContractTradeList = kwcContractTradeMapper.selectBatchIds(contractIdList);
        Date date = new Date();
        kwcContractTradeList.forEach(item -> {
            if (!item.getStatus().equals(ContractStatusEnum.SAVE.getCode())) {
                throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_022);
            }
            item.setDelFlag(Global.YES);
            item.setUpdateBy(LoginUserHolder.getUserId());
            item.setUpdateTime(date);
            if (kwcContractTradeMapper.updateById(item) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        });
    }

    /**
     * @param reqVo 查询入参
     * @desc: 导出
     * @author: czh
     * @date 2023/7/17
     */
    public void export(QueryListReqVo reqVo, HttpServletResponse response) {
        QueryListReqDto queryListReqDto = new QueryListReqDto();
        BeanUtils.copyProperties(reqVo, queryListReqDto);
        queryListReqDto.setIdList(StringUtils.splitStrToList(reqVo.getIds(), Global.COMMA, Long.class));
        List<Long> allEnt = new ArrayList<>();
        if (Objects.isNull(reqVo.getEntId())) {
            queryListReqDto.setEntId(LoginUserHolder.getEntId());
        }
        allEnt.add(queryListReqDto.getEntId());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(queryListReqDto.getEntId());
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        queryListReqDto.setAllEnt(allEnt);
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }

        List<QueryListResVo> list = getQueryListResVos(queryListResDtos, null, null);
        List<TradeListExport> dataList = BeanUtils.copyToList(list, TradeListExport.class);
        ExcelUtil.downData(response, TradeListExport.class, dataList);
    }

    /**
     * @return HttpResult
     * @desc: 查询当前企业的销售合同
     * @author: czh
     * @date: 2023/7/18
     */
    public List<QueryListResVo> queryCurrentEntSaleContractList() {
        Long entId = LoginUserHolder.getEntId();
        QueryListReqDto queryListReqDto = new QueryListReqDto();
        queryListReqDto.setEntId(entId);
        queryListReqDto.setStatus(ContractStatusEnum.SIGNED.getCode());
        queryListReqDto.setEntType(EntTypeEnum.SUPPLIER.getCode());
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            return Collections.emptyList();
        }
        return getQueryListResVos(queryListResDtos, null, null);
    }


    /**
     * @return FindListGroupResVo
     * @desc: 分组查询
     * @author: czh
     * @date: 2023/7/18
     */
    public List<FindListGroupResVo> findListGroup(QueryListReqVo reqVo) {
        ContractStatusEnum[] values = ContractStatusEnum.values();
        List<FindListGroupResVo> list = new ArrayList<>();
        FindListGroupResVo total = new FindListGroupResVo();
        total.setCount(0);
        list.add(total);
        for (ContractStatusEnum contractStatusEnum : values) {
            FindListGroupResVo findListGroupResVo = new FindListGroupResVo();
            findListGroupResVo.setStatus(contractStatusEnum.getCode());
            findListGroupResVo.setStatusName(contractStatusEnum.getName());
            findListGroupResVo.setCount(0);
            list.add(findListGroupResVo);
        }

        QueryListReqDto queryListReqDto = new QueryListReqDto();
        BeanUtils.copyProperties(reqVo, queryListReqDto);
        List<Long> allEnt = new ArrayList<>();
        if (Objects.isNull(reqVo.getEntId())) {
            queryListReqDto.setEntId(LoginUserHolder.getEntId());
        }
        allEnt.add(queryListReqDto.getEntId());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(queryListReqDto.getEntId());
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        queryListReqDto.setAllEnt(allEnt);
        List<QueryListResDto> queryListResDtoList = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isNotEmpty(queryListResDtoList)) {
            Map<Integer, List<QueryListResDto>> collect = queryListResDtoList.stream().collect(Collectors.groupingBy(QueryListResDto::getStatus));
            for (FindListGroupResVo findListGroupResVo : list) {
                List<QueryListResDto> queryListResDtos = collect.get(findListGroupResVo.getStatus());
                findListGroupResVo.setCount(CollectionUtils.isEmpty(queryListResDtos) ? Global.NUMERICAL_ZERO : queryListResDtos.size());
            }
            //给汇总项求和
            list.get(0).setCount(queryListResDtoList.size());
        }
        return list;
    }


    @Transactional(rollbackFor = {})
    public void approval(Long id, Integer status, String remark) {
        LambdaQueryWrapper<KwcContractTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwcContractTrade::getId, id).
                eq(KwcContractTrade::getDelFlag, Global.NO).
                eq(KwcContractTrade::getStatus, ContractStatusEnum.SUBMIT.getCode());
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectOne(wrapper);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }

        Date date = new Date();
        kwcContractTrade.setStatus(status);
        kwcContractTrade.setRemark(remark);
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
    }

    /**
     * @param reqVo 分页查询
     * @return PageResult
     * @desc: 运营端查贸易合同
     * @author: czh
     * @date: 2023/9/13
     */
    public PageResult queryTradeByPage(QueryListReqVo reqVo) {
        PageHelper.startPage(reqVo.getPageNum(), reqVo.getPageSize());

        //新增客户经理权限过滤
        List<Long> authEntIdList = LoginUserHolder.getAuthEntIdList();
        if (CollectionUtils.isEmpty(authEntIdList)) {
            List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
            if (CollectionUtils.isEmpty(ids)) {
                return PageHelperUtil.getPageResult(new PageInfo<>());
            }
            authEntIdList.addAll(ids);
        }

        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryTradeList(reqVo, authEntIdList);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            return PageHelperUtil.getPageResult(new PageInfo<>());
        }

        List<QueryListResVo> list = getTradeListResVo(queryListResDtos);
        return PageHelperUtil.getPageResult(new PageInfo<>(list), queryListResDtos, reqVo.getPageSize());
    }

    private List<QueryListResVo> getTradeListResVo(List<QueryListResDto> queryListResDtos) {
        Map<Long, UserCacheResDto> longUserCacheResDtoMap = new HashMap<>(8);
        List<Long> initiateByList = queryListResDtos.stream().map(QueryListResDto::getInitiateBy).toList();
        if (CollectionUtils.isNotEmpty(initiateByList)) {
            longUserCacheResDtoMap = remoteSystemService.queryUserCacheMapByIds(initiateByList);
        }

        List<QueryListResVo> list = new ArrayList<>();
        for (QueryListResDto queryListResDto : queryListResDtos) {
            QueryListResVo queryListResVo = new QueryListResVo();
            BeanUtils.copyProperties(queryListResDto, queryListResVo);

            UserCacheResDto userCacheResDto = longUserCacheResDtoMap.get(queryListResDto.getInitiateBy());
            if (Objects.nonNull(userCacheResDto)) {
                queryListResVo.setInitiateName(userCacheResDto.getName());
                queryListResVo.setInitiateEntName(Objects.isNull(userCacheResDto.getEntInfo()) ? "" : userCacheResDto.getEntInfo().getFirmName());
            }
            queryListResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(queryListResDto.getTrading())));
            queryListResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(queryListResDto.getStatus())).getName());
            queryListResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_TYPE.getType(), queryListResDto.getSigningWay()));
            queryListResVo.setSigningWay(queryListResDto.getSigningWay());
            queryListResVo.setAmount(queryListResDto.getAmount());
            queryListResVo.setPerformedAmount(queryListResDto.getPerformedAmount());
            list.add(queryListResVo);
        }
        return list;
    }

    /**
     * @return HttpResult
     * @desc: 分组查询
     * @author: czh
     * @date: 2023/7/18
     */
    public List<FindListGroupResVo> findTradeListGroup(QueryListReqVo reqVo) {
        ContractStatusEnum[] values = ContractStatusEnum.values();
        List<FindListGroupResVo> list = new ArrayList<>();
        FindListGroupResVo total = new FindListGroupResVo();
        total.setCount(0);
        list.add(total);
        for (ContractStatusEnum contractStatusEnum : values) {
            FindListGroupResVo findListGroupResVo = new FindListGroupResVo();
            findListGroupResVo.setStatus(contractStatusEnum.getCode());
            findListGroupResVo.setStatusName(contractStatusEnum.getName());
            findListGroupResVo.setCount(0);
            list.add(findListGroupResVo);
        }

        //新增客户经理权限过滤
        List<Long> authEntIdList = LoginUserHolder.getAuthEntIdList();
        if (CollectionUtils.isEmpty(authEntIdList)) {
            List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
            if (CollectionUtils.isEmpty(ids)) {
                return list;
            }
            authEntIdList.addAll(ids);
        }

        List<QueryListResDto> queryListResDtoList = kwcContractTradeMapper.queryTradeList(reqVo, authEntIdList);
        if (CollectionUtils.isNotEmpty(queryListResDtoList)) {
            Map<Integer, List<QueryListResDto>> collect = queryListResDtoList.stream().collect(Collectors.groupingBy(QueryListResDto::getStatus));
            for (FindListGroupResVo findListGroupResVo : list) {
                List<QueryListResDto> queryListResDtos = collect.get(findListGroupResVo.getStatus());
                findListGroupResVo.setCount(CollectionUtils.isEmpty(queryListResDtos) ? Global.NUMERICAL_ZERO : queryListResDtos.size());
            }
            //给汇总项求和
            list.get(0).setCount(queryListResDtoList.size());
        }
        return list;
    }


    /**
     * @param reqVo 查询参数
     * @desc: 运营端查贸易合同导出
     * @author: czh
     * @date: 2023/9/13
     */
    public void exportTradeList(QueryListReqVo reqVo, HttpServletResponse response) {
        reqVo.setIdList(StringUtils.splitStrToList(reqVo.getIds(), Global.COMMA, Long.class));

        //新增客户经理权限过滤
        List<Long> authEntIdList = LoginUserHolder.getAuthEntIdList();
        if (CollectionUtils.isEmpty(authEntIdList)) {
            List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
            if (CollectionUtils.isEmpty(ids)) {
                throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
            }
            authEntIdList.addAll(ids);
        }

        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryTradeList(reqVo, authEntIdList);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }
        List<QueryListResVo> list = getTradeListResVo(queryListResDtos);
        List<TradeListExport> dataList = BeanUtils.copyToList(list, TradeListExport.class);
        ExcelUtil.downData(response, TradeListExport.class, dataList);
    }

    public PageDataResult<QueryTradeContractResp> queryTradeContractByPage(QueryTradeContractReq req) {
        return PageDataResult.empty(req.getPageNum(), req.getPageSize());
    }

    @Transactional(rollbackFor = Exception.class)
    public void addSupplyTradeContract(@Valid SupplyContractTradeReq req) {
        log.info("补充合同请求参数，req:{}", JSON.toJSONString(req));
        //校验标的信息是否有重复
        checkParams(req);
        //校验合同基本信息
        checkParam(req.getBaseInfo());
        //保存补充合同
        long contactId = new IdWorker(1L).nextId();
        saveTradeContract(req, contactId);

        //获取商品id
        List<Long> goodsIds = req.getGoodsInfo()
                .stream()
                .map(SupplyContractTradeReq.TradeGoodsInfo::getGoodsId)
                .collect(Collectors.toList());


        //根据父id查询补充合同id
        Set<Long> contractIds = Sets.newHashSet();
        List<KwcContractTrade> kwcContractTrades = kwcContractTradeRepository.queryByPid(req.getPid());
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwcContractTrades)) {
            contractIds.addAll(kwcContractTrades.stream()
                    .map(KwcContractTrade::getId)
                    .collect(Collectors.toSet()));
        }

        //获取合同id
        contractIds.add(req.getPid());
        //查询标的信息
        //根据商品id查询标的信息和主合同
        List<KwcContractTradeGoods> kwcContractTradeGoods =
                kwcContractTradeGoodsRepository.queryByConTractIdsGoodsIds(contractIds, goodsIds);
        //商品id映射商品信息（排除主合同查看是否存在补充合同的商品信息）
        Map<Long, KwcContractTradeGoods> goodsIdAndGoodsMap = kwcContractTradeGoods.stream()
                .filter(x -> !Objects.equals(x.getContractId(), req.getPid()))
                .collect(Collectors.toMap(KwcContractTradeGoods::getGoodsId, Function.identity(), (x, y) -> x));
        //过滤主合同查看的标信息 , 合同id商品id组成唯一key映射商品信息
        Map<String, KwcContractTradeGoods> contractTradeKeyAndGoodsMap =
                kwcContractTradeGoods.stream().filter(x -> Objects.equals(x.getContractId(), req.getPid()))
                        .peek(x -> x.setContractIdGoodsIdKey(x.getContractId() + "-" + x.getGoodsId()))
                        .collect(Collectors.toMap(KwcContractTradeGoods::getContractIdGoodsIdKey, Function.identity(), (x, y) -> x));

        //商品id映射交易商品信息
        List<KwcContractTradeGoods> saveOrUpdateTradeGoods = Lists.newArrayList();
        req.getGoodsInfo().forEach(g -> {
            KwcContractTradeGoods tradeGoods = goodsIdAndGoodsMap.get(g.getGoodsId());
            if (Objects.isNull(tradeGoods)) {
                //作为新增对象
                buildTradeGoods(req, g, contractTradeKeyAndGoodsMap, saveOrUpdateTradeGoods, contactId);

            } else {
                //如果不为空判断时间是否重叠 存在则报错
                if (g.getEffectiveStartTime().after(tradeGoods.getStartTime()) && g.getEffectiveStartTime().before(tradeGoods.getEndTime())
                        || (g.getEffectiveEntTime().after(tradeGoods.getStartTime()) && g.getEffectiveEntTime().before(tradeGoods.getEndTime()))) {
                    throw new BusinessException("商品:" + g.getGoodsName() + "时间重叠,只有先结束之前的补充合同,才能进行创建；");
                }
                buildTradeGoods(req, g, contractTradeKeyAndGoodsMap, saveOrUpdateTradeGoods, contactId);
            }
        });

        kwcContractTradeGoodsRepository.saveOrUpdateBatch(saveOrUpdateTradeGoods);

        //存单位信息
        TradeBaseInfoReqVo baseInfoReqVo = new TradeBaseInfoReqVo();
        org.springframework.beans.BeanUtils.copyProperties(req.getBaseInfo(), baseInfoReqVo);
        kwcContractTradeUnitService.saveContractTradeUnit(contactId, baseInfoReqVo);

    }

    private static void buildTradeGoods(SupplyContractTradeReq req, SupplyContractTradeReq.TradeGoodsInfo g,
                                        Map<String, KwcContractTradeGoods> contractTradeKeyAndGoodsMap,
                                        List<KwcContractTradeGoods> saveTradeGoods, long contactId) {
        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        KwcContractTradeGoods saveSupplyTradeGoods = new KwcContractTradeGoods();
        saveSupplyTradeGoods.setContractId(contactId);
        saveSupplyTradeGoods.setGoodsId(g.getGoodsId());
        saveSupplyTradeGoods.setSkuId(0L);
        saveSupplyTradeGoods.setAmount(g.getAmount());
        saveSupplyTradeGoods.setUnit(g.getUnit());
        saveSupplyTradeGoods.setPrice(g.getPrice());
        saveSupplyTradeGoods.setPerformedAmount(new BigDecimal("0"));
        saveSupplyTradeGoods.setStatus(Global.NO);
        saveSupplyTradeGoods.setCreateBy(userId);
        saveSupplyTradeGoods.setCreateTime(date);
        saveSupplyTradeGoods.setUpdateBy(userId);
        saveSupplyTradeGoods.setUpdateTime(date);
        saveSupplyTradeGoods.setDelFlag(Global.NO);
        saveSupplyTradeGoods.setStartTime(g.getEffectiveStartTime());
        saveSupplyTradeGoods.setEndTime(g.getEffectiveEntTime());
        //修改主合同商品数量

        KwcContractTradeGoods tradeGoodsData =
                contractTradeKeyAndGoodsMap.get(req.getPid() + "-" + g.getGoodsId());
        if (Objects.nonNull(tradeGoodsData)) {
            KwcContractTradeGoods mainTradeGoods = new KwcContractTradeGoods();
            mainTradeGoods.setId(tradeGoodsData.getId());
            mainTradeGoods.setPrice(g.getPrice());
            mainTradeGoods.setAmount(g.getAmount());
            saveTradeGoods.add(mainTradeGoods);
        }
        saveTradeGoods.add(saveSupplyTradeGoods);
    }

    private void saveTradeContract(SupplyContractTradeReq req, long contactId) {
        SupplyContractTradeReq.TradeBaseInfo baseInfo = req.getBaseInfo();
        List<SupplyContractTradeReq.TradeGoodsInfo> goodsInfo = req.getGoodsInfo();
        Date date = new Date();
        KwcContractTrade kwcContractTrade = new KwcContractTrade();
        kwcContractTrade.setEntId(LoginUserHolder.getEntId());
        kwcContractTrade.setContractNo(baseInfo.getContractCode());
        kwcContractTrade.setName(baseInfo.getContractName());
        kwcContractTrade.setSigningWay(baseInfo.getSigningWay());
        kwcContractTrade.setTrading(baseInfo.getTrading());
        kwcContractTrade.setStartTime(baseInfo.getStartTime());
        if (Objects.nonNull(baseInfo.getEndTime())) {
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(baseInfo.getEndTime()));
        }
        kwcContractTrade.setPerformedAmount(new BigDecimal("0"));
        kwcContractTrade.setContractPid(req.getPid());
        kwcContractTrade.setRemark(req.getRemark());
        kwcContractTrade.setCreateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setCreateTime(date);
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setDelFlag(Global.NO);

        kwcContractTrade.setSettlement(baseInfo.getSettlement());
        kwcContractTrade.setConsignment(baseInfo.getConsignment());
        kwcContractTrade.setUnloadWay(baseInfo.getUnloadWay());
        kwcContractTrade.setSalesmanId(baseInfo.getSalesmanId());
        kwcContractTrade.setSalesmanPhone(baseInfo.getSalesmanPhone());
        kwcContractTrade.setDispatchWay(baseInfo.getDispatchWay());


        BigDecimal amountTotal = new BigDecimal(Global.NUMERICAL_ZERO);
        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (SupplyContractTradeReq.TradeGoodsInfo tradeGoodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(tradeGoodsInfoReqVo.getAmount())) {
                    amountTotal = amountTotal.add(tradeGoodsInfoReqVo.getAmount());
                }
            }
        }
        kwcContractTrade.setAmount(amountTotal);

        kwcContractTrade.setId(contactId);
        kwcContractTrade.setSigningUrl(req.getContractFile());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(LoginUserHolder.getEntId());
        if (Objects.nonNull(entCacheResDto) && StringUtils.isNotBlank(entCacheResDto.getEntTypes())) {
            if (org.apache.commons.lang3.StringUtils.equals(entCacheResDto.getEntTypes(), String.valueOf(EntTypeEnum.SUPPLIER.getCode()))) {
                kwcContractTrade.setStatus(ContractStatusEnum.WAIT_APPROVE.getCode());
            } else if (org.apache.commons.lang3.StringUtils.equals(entCacheResDto.getEntTypes(), String.valueOf(EntTypeEnum.PURCHASER.getCode()))) {
                kwcContractTrade.setStatus(ContractStatusEnum.SUBMIT.getCode());
            }
        }
        if (kwcContractTradeMapper.insert(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    private static void checkParams(SupplyContractTradeReq req) {
        if (hasDuplicateGoodsIds(req.getGoodsInfo())) {
            throw new BusinessException("标信息有重复");
        }
        //判断时间大小
        boolean startTimeBefore = req.getGoodsInfo().stream()
                .filter(t -> Objects.nonNull(t.getEffectiveStartTime()) && Objects.nonNull(req.getBaseInfo().getStartTime()))
                .anyMatch(t -> t.getEffectiveStartTime().before(req.getBaseInfo().getStartTime()));
        if (startTimeBefore) {
            throw new BusinessException("标信息开始时间不能早于合同开始时间");
        }
        boolean endTimeAfter = req.getGoodsInfo().stream()
                .filter(t -> Objects.nonNull(t.getEffectiveEntTime()) && Objects.nonNull(req.getBaseInfo().getEndTime()))
                .anyMatch(t -> t.getEffectiveEntTime().after(req.getBaseInfo().getEndTime()));
        if (endTimeAfter) {
            throw new BusinessException("标信息结束时间不能晚于合同结束时间");
        }
        boolean b = req.getGoodsInfo().stream()
                .filter(t -> Objects.nonNull(t.getEffectiveEntTime()) && Objects.nonNull(t.getEffectiveStartTime()))
                .anyMatch(t -> t.getEffectiveEntTime().before(t.getEffectiveStartTime()));
        if (b) {
            throw new BusinessException("标信息结束时间不能早于开始时间");
        }
    }

    private void checkParam(SupplyContractTradeReq.TradeBaseInfo baseInfo) {
        if (Objects.nonNull(baseInfo)) {
//            if (StringUtils.isNotBlank(baseInfo.getContractCode()) && baseInfo.getContractCode().length() > 20) {
//                throw new SystemException("合同编号超长！");
//            }
//
//            if (StringUtils.isNotBlank(baseInfo.getContractName()) && baseInfo.getContractName().length() > 20) {
//                throw new SystemException("合同名称超长！");
//            }
            if (Objects.equals(baseInfo.getSettlement(), 1)) {
                throw new SystemException("暂不支持普通结算模式！");
            }
        }

        if (Objects.equals(DispatchWayEnums.MANUAL_DISPATCH.getCode(), baseInfo.getDispatchWay())) {
            if (baseInfo.getConsignment() == null) {
                throw new SystemException("派车方式为手动派单时，托运方式不能为空！");
            }
        }
        KwcContractTrade kwcContractTrade = kwcContractTradeRepository.queryByContractNo(baseInfo.getContractCode());
        if (Objects.nonNull(kwcContractTrade)) {
            throw new SystemException("合同编号已存在！");
        }
    }


    private static boolean hasDuplicateGoodsIds(List<SupplyContractTradeReq.TradeGoodsInfo> goodsInfo) {
        if (goodsInfo == null || goodsInfo.isEmpty()) {
            return false;
        }

        Set<Long> goodsIdSet = new HashSet<>();
        for (SupplyContractTradeReq.TradeGoodsInfo info : goodsInfo) {
            if (info.getGoodsId() != null) {
                if (!goodsIdSet.add(info.getGoodsId())) {
                    return true;
                }
            }
        }
        return false;
    }

    public Boolean updateStatus(@Valid ApprovalReq req) {
        log.info("修改合同状态，请求参数 :{}", JSON.toJSONString(req));
        //查询本地商品合同信息
        KwcContractTrade kwcContractTrade = kwcContractTradeRepository.queryByContractId(Long.valueOf(req.getContractId()));
        if (Objects.isNull(kwcContractTrade)) {
            throw new BusinessException("合同不存在");
        }
        //创建修改对象
        KwcContractTrade updateKwcContractTrade = new KwcContractTrade();
        updateKwcContractTrade.setId(kwcContractTrade.getId());
        updateKwcContractTrade.setRemark(req.getRemark());
        //审核  审核后变成待签约
        //审核拒绝 （状态由待审核变成已作废）
        if (Objects.equals(req.getStatus(), ContractStatusEnum.CANNEL.getCode())
                && Arrays.asList(ContractStatusEnum.WAIT_APPROVE.getCode(), ContractStatusEnum.SUBMIT.getCode()).contains(kwcContractTrade.getStatus())) {
            updateKwcContractTrade.setStatus(ContractStatusEnum.CANNEL.getCode());
        }
        //签约 （状态由带签约或者待审核变成签约）
        if (Objects.equals(req.getStatus(), ContractStatusEnum.SIGNED.getCode()) &&
                Arrays.asList(ContractStatusEnum.SUBMIT.getCode(), ContractStatusEnum.WAIT_APPROVE.getCode(), ContractStatusEnum.CANNEL.getCode())
                        .contains(kwcContractTrade.getStatus())) {
            updateKwcContractTrade.setStatus(ContractStatusEnum.SIGNED.getCode());
            updateKwcContractTrade.setSignTime(new Date());
        }
        //手动完结 (如果不传状态就表示手动完结) 如果当前状态是待签约或者待签约 那么变为作废
        if (Objects.equals(req.getStatus(), ContractStatusEnum.CANNEL.getCode()) && Arrays.asList(ContractStatusEnum.WAIT_APPROVE.getCode(),
                ContractStatusEnum.SUBMIT.getCode()).contains(kwcContractTrade.getStatus())) {
            updateKwcContractTrade.setStatus(ContractStatusEnum.CANNEL.getCode());
        }
        //手动完结 如果当前的状态是已经签约，订单变成已完结
        if (Objects.equals(req.getStatus(), ContractStatusEnum.COMPLETE.getCode()) && Objects.equals(kwcContractTrade.getStatus(),
                ContractStatusEnum.SIGNED.getCode())) {
            updateKwcContractTrade.setStatus(ContractStatusEnum.COMPLETE.getCode());
        }
        Boolean result = kwcContractTradeRepository.updateByContractId(updateKwcContractTrade);
        if (Objects.equals(req.getStatus(), ContractStatusEnum.SIGNED.getCode()) && Objects.equals(updateKwcContractTrade.getStatus(), ContractStatusEnum.SIGNED.getCode())) {
            //签约成功，初始化预付清单
            //根据订单号查询交易企业信息
            List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractId(kwcContractTrade.getId());
            Map<Integer, KwcContractTradeUnit> collect = tradeUnits.stream().collect(Collectors.toMap(KwcContractTradeUnit::getUnitType, Function.identity(), (x, y) -> x));
            WalletPrepaidDto prepaidDto = new WalletPrepaidDto();
            prepaidDto.setProEntId(collect.get(CooperateTypeEnum.PURCHASER.getCode()).getEntId());
            prepaidDto.setSupEntId(collect.get(CooperateTypeEnum.SUPPLIER.getCode()).getEntId());
            prepaidDto.setTradeAmount(BigDecimal.ZERO);
            prepaidDto.setRemark("预付清单初始化");
            log.info("采购商:{}与供应商:{}签订贸易合同，预付清单初始化",prepaidDto.getProEntId(),prepaidDto.getSupEntId());
            BaseResult<Object> prepaidResult = paymentFeignService.initPrepaidBalance(prepaidDto);
            if (prepaidResult.getCode() == HttpStatus.SUCCESS_CODE) {
                log.info("创建预付清单成功");
            } else {
                log.error("创建预付清单失败");
                throw new BusinessException("创建预付清单失败");
            }
        }
        return result;

    }

    public ContractDetailResp queryContractDetail(@Valid ContractDetailReq req) {
        log.info("查询合同详情，请求参数 :{}", JSON.toJSONString(req));
        //查询本地商品合同信息
        KwcContractTrade kwcContractTrade = kwcContractTradeRepository.queryByContractId(Long.valueOf(req.getContractId()));
        if (Objects.isNull(kwcContractTrade)) {
            return new ContractDetailResp();
        }
        //根据订单号查询交易企业信息
        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractId(kwcContractTrade.getId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits)) {
            return new ContractDetailResp();
        }
        //安装合同id和单位类型组合成key映射公司对象
        Map<String, KwcContractTradeUnit> ctTypeKeyAndUnitMap = tradeUnits.stream()
                .peek(t -> t.setContractIdUniTypeKey(t.getContractId() + "-" + t.getUnitType()))
                .collect(Collectors.toMap(KwcContractTradeUnit::getContractIdUniTypeKey, Function.identity(),
                        (v1, v2) -> v1));

        //查询商品合同
        List<KwcContractTradeGoods> tradeGoods = kwcContractTradeGoodsRepository.queryByContractId(kwcContractTrade.getId());
        List<Long> goodsIds = Lists.newArrayList();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tradeGoods)) {
            //获取商品id
            goodsIds = tradeGoods.stream()
                    .map(KwcContractTradeGoods::getGoodsId)
                    .distinct()
                    .collect(Collectors.toList());

        }
        //查询商品 商品id映射商品
        Map<Long, KwpGoods> goodsIdAndGoodsMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(goodsIds)) {
            goodsIdAndGoodsMap = goodsInfoService.getGoodsByIds(goodsIds);

        }

        //查询字典
        Map<String, Map<String, String>> dictValueAndDictResDtoMap = remoteSystemService.queryDictByType(Arrays.asList(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.GOODS_SPEC.getType()));

        ContractDetailResp contractDetailResp = new ContractDetailResp();
        contractDetailResp.setId(kwcContractTrade.getId());
        contractDetailResp.setPid(kwcContractTrade.getContractPid());
        //获取基本信息
        ContractDetailResp.TradeBaseInfo baseInfo = getBaseInfo(ctTypeKeyAndUnitMap, kwcContractTrade);
        contractDetailResp.setBaseInfo(baseInfo);
        //文件合同
        contractDetailResp.setContractFile(kwcContractTrade.getSigningUrl());

        //标地信息
        if (CollectionUtils.isNotEmpty(tradeGoods)) {
            Map<Long, KwpGoods> finalGoodsIdAndGoodsMap = goodsIdAndGoodsMap;
            List<ContractDetailResp.TradeGoodsInfo> tradeGoodsInfos = tradeGoods.stream()
                    .map(t -> getTradeGoodsInfo(t, finalGoodsIdAndGoodsMap, dictValueAndDictResDtoMap))
                    .collect(Collectors.toList());
            contractDetailResp.setGoodsInfo(tradeGoodsInfos);
        }


        contractDetailResp.setRemark(kwcContractTrade.getRemark());

        return contractDetailResp;
    }


    private static ContractDetailResp.TradeGoodsInfo getTradeGoodsInfo(KwcContractTradeGoods t,
                                                                       Map<Long, KwpGoods> finalGoodsIdAndGoodsMap,
                                                                       Map<String, Map<String, String>> dictValueAndDictResDtoMap) {
        ContractDetailResp.TradeGoodsInfo tradeGoodsInfo = new ContractDetailResp.TradeGoodsInfo();
        tradeGoodsInfo.setGoodsId(t.getGoodsId());
        KwpGoods goods = finalGoodsIdAndGoodsMap.getOrDefault(t.getGoodsId(), new KwpGoods());
        Map<String, String> goodsTypeMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), new HashMap<>());
        Map<String, String> goodsSpecMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.GOODS_SPEC.getType(), new HashMap<>());
        tradeGoodsInfo.setGoodsName(goods.getName() + "/" + goodsTypeMap.getOrDefault(goods.getGoodsType(), "") + "/" + goodsSpecMap.getOrDefault(goods.getSpec(), ""));
        tradeGoodsInfo.setAmount(t.getAmount());
        tradeGoodsInfo.setPrice(t.getPrice());
        tradeGoodsInfo.setUnit(DictEnum.getLabel(DictTypeEnum.UNIT_TYPE.getType(), t.getUnit()));
        tradeGoodsInfo.setEffectiveStartTime(t.getStartTime());
        tradeGoodsInfo.setEffectiveEntTime(t.getEndTime());
        return tradeGoodsInfo;
    }

    private static ContractDetailResp.TradeBaseInfo getBaseInfo(Map<String, KwcContractTradeUnit> ctTypeKeyAndUnitMap, KwcContractTrade kwcContractTrade) {
        ContractDetailResp.TradeBaseInfo tradeBaseInfo = new ContractDetailResp.TradeBaseInfo();
        KwcContractTradeUnit purchaseUnit =
                ctTypeKeyAndUnitMap.getOrDefault(kwcContractTrade.getId() + "-" + CooperateTypeEnum.PURCHASER.getCode(), new KwcContractTradeUnit());
        tradeBaseInfo.setPurchaseEntId(purchaseUnit.getEntId());

        tradeBaseInfo.setPurchaseFirmName(purchaseUnit.getFirmName());
        tradeBaseInfo.setPurchasePhone(purchaseUnit.getPhone());
        KwcContractTradeUnit provideUnit =
                ctTypeKeyAndUnitMap.getOrDefault(kwcContractTrade.getId() + "-" + CooperateTypeEnum.SUPPLIER.getCode(), new KwcContractTradeUnit());
        tradeBaseInfo.setProvideEntId(provideUnit.getEntId());
        tradeBaseInfo.setProvideFirmName(provideUnit.getFirmName());
        tradeBaseInfo.setProvidePhone(provideUnit.getPhone());
        tradeBaseInfo.setContractCode(kwcContractTrade.getContractNo());
        tradeBaseInfo.setContractName(kwcContractTrade.getName());
        tradeBaseInfo.setContractStatus(String.valueOf(kwcContractTrade.getStatus()));
        tradeBaseInfo.setContractStatusDesc(ContractStatusEnum.getNameByCode(kwcContractTrade.getStatus()));
        if (Objects.nonNull(kwcContractTrade.getEndTime())) {
            tradeBaseInfo.setEndTime(kwcContractTrade.getEndTime());
            String endDate = DateUtils.format(kwcContractTrade.getEndTime(), DateUtils.DATE_PATTERN);
            if (org.apache.commons.lang3.StringUtils.equals(endDate, "9999-12-30")) {
                tradeBaseInfo.setEndTime(null);
            }
        }

        tradeBaseInfo.setSigningWay(kwcContractTrade.getSigningWay());
        tradeBaseInfo.setSigningWayDesc(DictEnum.getLabel(DictTypeEnum.SIGNING_WAY.getType(), String.valueOf(kwcContractTrade.getSigningWay())));
        tradeBaseInfo.setStartTime(kwcContractTrade.getStartTime());
        tradeBaseInfo.setSettlement(kwcContractTrade.getSettlement());
        tradeBaseInfo.setSettlementDesc(DictEnum.getLabel(DictTypeEnum.SETTLEMENT_WAY.getType(),
                String.valueOf(kwcContractTrade.getSettlement())));
        tradeBaseInfo.setConsignment(kwcContractTrade.getConsignment());
        tradeBaseInfo.setConsignmentDesc(DictEnum.getLabel(DictTypeEnum.CONSIGNMENT_WAY.getType(),
                String.valueOf(kwcContractTrade.getConsignment())));

        tradeBaseInfo.setUnloadWay(kwcContractTrade.getUnloadWay());
        tradeBaseInfo.setUnloadWayDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),
                String.valueOf(kwcContractTrade.getUnloadWay())));
        tradeBaseInfo.setSalesmanId(kwcContractTrade.getSalesmanId());
        tradeBaseInfo.setSalesmanPhone(kwcContractTrade.getSalesmanPhone());
        tradeBaseInfo.setMeasurementWay(Objects.equals(kwcContractTrade.getMeasurementWay(), -1) ? null : kwcContractTrade.getMeasurementWay());
        tradeBaseInfo.setMeasurementWayDesc(Objects.equals(kwcContractTrade.getMeasurementWay(), -1) ? "" : DictEnum.getLabel(String.valueOf(kwcContractTrade.getMeasurementWay())));
        tradeBaseInfo.setDispatchWay(kwcContractTrade.getDispatchWay());
        tradeBaseInfo.setDispatchWayDesc(Optional.ofNullable(kwcContractTrade.getDispatchWay()).map(DispatchWayEnums::getDesc).orElse(""));
        return tradeBaseInfo;
    }

    public List<QueryListResVo> queryTradeListByPage(QueryTradeReq req) {

        Long entId;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getEntId())) {
            entId = Long.valueOf(req.getEntId());
        } else {
            entId = LoginUserHolder.getEntId();
        }
        // Integer type = null;
        Set<Long> entIds = Sets.newHashSet();
        entIds.add(entId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
            //查询企业 信息
            entIds.add(Long.valueOf(req.getPurchaseEntId()));
            //  type = CooperateTypeEnum.PURCHASER.getCode();
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            entIds.add(Long.valueOf(req.getSupplyEntId()));
            //type = CooperateTypeEnum.SUPPLIER.getCode();
        }
        Set<Long> contractIds = buildTradeQueryContractIds(entId, req, entIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
            return Collections.emptyList();
        }
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        //分页查询合同信息
        List<KwcContractTrade> records = kwcContractTradeRepository.queryTradeListByPageList(
                req.getContractCode(),
                req.getContractName(),
                req.getSupplementCode(),
                contractIds, req.getStatus(), req.getDispatchWay(), req.getPageNum(), req.getPageSize());
        // List<KwcContractTrade> records = page.getRecords();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return Collections.emptyList();
        }
        // 数据权限：企业按 kwc_contract_trade_unit；与销售员条件见 filterTradeContractsByPermission
        DataPermissionDTO perm = fetchDataPermissionForCurrentUser();
        records = filterTradeContractsByPermission(records, perm);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return Collections.emptyList();
        }
        entIds.addAll(records.stream().map(KwcContractTrade::getEntId).collect(Collectors.toSet()));
        List<EntTypeResDto> ents = remoteSystemService.queryEntTypeByIds(entIds);
        Map<Long, EntTypeResDto> entIdAndEntMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(ents)) {
            entIdAndEntMap =
                    ents.stream().collect(Collectors.toMap(EntTypeResDto::getEntId, Function.identity(), (v1, v2) -> v1));
        }
        //如果登录方是采购方，创建方是提供方，那么采购方只能看到已经签约的合同
        EntTypeResDto entTypeResDto = entIdAndEntMap.getOrDefault(entId, new EntTypeResDto());
        //如果登录方是采购商，创建方是供应方，那么采购商只能看到已经签约的合同
        List<KwcContractTrade> contractTrades = Lists.newArrayList();
        List<KwcContractTrade> contractTrades1 = Lists.newArrayList();
        if (entTypeResDto.getType().equals(EntTypeEnum.PURCHASER.getCode())) {
            List<Integer> statusList = Arrays.asList(ContractStatusEnum.SIGNED.getCode(), ContractStatusEnum.COMPLETE.getCode());
            Map<Long, EntTypeResDto> finalEntIdAndEntMap1 = entIdAndEntMap;

            records.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap1.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode()) && statusList.contains(record.getStatus())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        //如果登录方是供应方，创建方是采购方，那么供应方不能看到已作废的 合同
        if (entTypeResDto.getType().equals(EntTypeEnum.SUPPLIER.getCode())) {
            Map<Long, EntTypeResDto> finalEntIdAndEntMap = entIdAndEntMap;
            records.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode()) && !Objects.equals(record.getStatus(), ContractStatusEnum.CANNEL.getCode())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        contractTrades.addAll(contractTrades1);
        records = contractTrades;
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return Collections.emptyList();
        }

        Set<Long> tradeContractIds = records.stream().map(KwcContractTrade::getId).collect(Collectors.toSet());
        //获取父id
        Set<Long> contractPids = records.stream().map(KwcContractTrade::getContractPid).collect(Collectors.toSet());
        //根据父id查询父合同信息
        Map<Long, KwcContractTrade> pidIdAndTradeMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(contractPids)) {
            List<KwcContractTrade> contractPidList = kwcContractTradeRepository.queryByContractIds(contractPids);

            pidIdAndTradeMap =
                    contractPidList.stream().collect(Collectors.toMap(KwcContractTrade::getId
                            , Function.identity(), (v1, v2) -> v1));
        }

        //查询公司信息
        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractIds(tradeContractIds);
        Map<String, KwcContractTradeUnit> contractUnitTypeKeyAndUnitMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tradeUnits)) {
            contractUnitTypeKeyAndUnitMap = tradeUnits.stream()
                    .peek(x -> x.setContractIdUniTypeKey(x.getContractId() + "-" + x.getUnitType()))
                    .collect(Collectors.toMap(KwcContractTradeUnit::getContractIdUniTypeKey, Function.identity(), (v1
                            , v2) -> v1));
        }
        //查询用户信息
        //获取创建人
        List<Long> createBys =
                records.stream().map(KwcContractTrade::getCreateBy).distinct().collect(Collectors.toList());
        Map<Long, UserCacheResDto> longUserCacheResDtoMap = remoteSystemService.queryUserCacheMapByIds(createBys);
        //根据物流查询贸易订单
        List<TradeOrderContractVo> tradeOrderContractVos = tradeOrderInfoService.queryByTradeContactIds(tradeContractIds);
        Map<Long, RWaybillSubOrderVo> tradeOrderIdAndWaybillMap = Maps.newHashMap();
        Map<Long, TradeOrderContractVo> contractIdAndContractMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tradeOrderContractVos)) {
            contractIdAndContractMap = tradeOrderContractVos.stream()
                    .collect(Collectors.toMap(TradeOrderContractVo::getContractId, Function.identity(), (v1, v2) -> v1));
            //贸易订单id
            Set<Long> tradeOrderIds = tradeOrderContractVos.stream()
                    .map(TradeOrderContractVo::getTOrderId)
                    .collect(Collectors.toSet());
            //通过贸易订单id查询物流运单
            List<RWaybillSubOrderVo> rWaybillSubOrderVos = transportRemoteService.queryWaybillOrderByTradeOrderIds(tradeOrderIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(rWaybillSubOrderVos)) {
                tradeOrderIdAndWaybillMap = rWaybillSubOrderVos.stream()
                        .collect(Collectors.toMap(RWaybillSubOrderVo::getTradeId, Function.identity(), (k1, k2) -> k1));
            }
        }
        //根据合同id查询合同商品
        List<KwcContractTradeGoods> tradeGoods = kwcContractTradeGoodsRepository.queryByContractIds(tradeContractIds);
        Map<Long, KwcContractTradeGoods> goodsIdAndGoodsMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tradeGoods)) {
            goodsIdAndGoodsMap = tradeGoods.stream().collect(Collectors.toMap(KwcContractTradeGoods::getGoodsId, Function.identity(), (v1, v2) -> v1));
        }

        Map<Long, KwcContractTrade> finalPidIdAndTradeMap = pidIdAndTradeMap;
        Map<String, KwcContractTradeUnit> finalContractUnitTypeKeyAndUnitMap = contractUnitTypeKeyAndUnitMap;
        Map<Long, RWaybillSubOrderVo> finalTradeOrderIdAndWaybillMap = tradeOrderIdAndWaybillMap;
        Map<Long, TradeOrderContractVo> finalContractIdAndContractMap = contractIdAndContractMap;
        Map<Long, KwcContractTradeGoods> finalGoodsIdAndGoodsMap = goodsIdAndGoodsMap;
        List<QueryListResVo> queryListResVos = records.stream()
                .map(t -> getQueryListResVo(t, finalContractUnitTypeKeyAndUnitMap, finalPidIdAndTradeMap, longUserCacheResDtoMap,
                        finalTradeOrderIdAndWaybillMap, finalContractIdAndContractMap, finalGoodsIdAndGoodsMap))
                .collect(Collectors.toList());
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
            queryListResVos = queryListResVos.stream()
                    .filter(x -> org.apache.commons.lang3.StringUtils.equals(x.getPurchaseEntId(), req.getPurchaseEntId()))
                    .collect(Collectors.toList());
        }

        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            queryListResVos = queryListResVos.stream()
                    .filter(x -> org.apache.commons.lang3.StringUtils.equals(x.getProvideEntId(), req.getSupplyEntId()))
                    .collect(Collectors.toList());
        }
        return queryListResVos.stream()
                .sorted(Comparator.comparing(QueryListResVo::getUpdateTime).reversed()
                        .thenComparing(Comparator.comparing(QueryListResVo::getId).reversed()))
                .collect(Collectors.toList());
    }


    /**
     * 构建贸易合同查询的合同ID集合。
     * <p>
     * 根据当前登录企业ID、采购方企业ID、供应方企业ID等条件，从合同关联单位表中筛选出符合条件的合同ID。
     * 主要用于分页查询和总数统计时的数据过滤。
     * </p>
     *
     * @param entId  当前登录的企业ID
     * @param req    查询请求参数，包含采购方ID、供应方ID等过滤条件
     * @param entIds 参与查询的所有相关企业ID集合（包括当前企业、指定的采购/供应企业等）
     * @return 符合条件的合同ID集合，若无匹配则返回空集合
     */
    private Set<Long> buildTradeQueryContractIds(Long entId, QueryTradeReq req, Set<Long> entIds) {
        // 1. 基础参数校验：如果当前企业ID为空或关联企业ID集合为空，直接返回空集合
        if (Objects.isNull(entId) || org.apache.commons.collections4.CollectionUtils.isEmpty(entIds)) {
            log.debug("构建贸易合同查询ID失败：entId为空或entIds集合为空, entId: {}", entId);
            return Collections.emptySet();
        }

        // 2. 查询这些企业关联的所有合同单位信息
        List<KwcContractTradeUnit> units = kwcContractTradeUnitRepository.queryByEntIds(entIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(units)) {
            log.debug("构建贸易合同查询ID失败：未查询到任何合同单位信息, entIds: {}", entIds);
            return Collections.emptySet();
        }
        log.debug("查询到合同单位数量: {}, entIds: {}", units.size(), entIds);

        // 3. 初步筛选：获取当前登录企业（entId）参与的所有合同ID
        Set<Long> contractIds = units.stream()
                .filter(unit -> Objects.equals(unit.getEntId(), entId))
                .map(KwcContractTradeUnit::getContractId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
            log.debug("构建贸易合同查询ID失败：当前企业[{}]未参与任何合同", entId);
            return Collections.emptySet();
        }
        log.debug("当前企业[{}]参与的初始合同ID数量: {}", entId, contractIds.size());

        // 4. 如果指定了采购方企业ID，则取交集：只保留该采购方作为“采购角色”参与的合同
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
            Long purchaseEntId = Long.valueOf(req.getPurchaseEntId());
            log.debug("应用采购方过滤条件: purchaseEntId = {}", purchaseEntId);
            
            Set<Long> purchaseContractIds = units.stream()
                    .filter(unit -> Objects.equals(unit.getEntId(), purchaseEntId))
                    // 必须明确 unitType 为 PURCHASER (采购方)
                    .filter(unit -> Objects.equals(unit.getUnitType(), CooperateTypeEnum.PURCHASER.getCode()))
                    .map(KwcContractTradeUnit::getContractId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            
            // 取交集：合同必须同时出现在当前企业的合同列表 和 指定采购方的合同列表中
            int beforeSize = contractIds.size();
            contractIds.retainAll(purchaseContractIds);
            log.debug("采购方过滤后剩余合同数量: {} (原数量: {})", contractIds.size(), beforeSize);
        }

        // 5. 如果指定了供应方企业ID，则取交集：只保留该供应方作为“供应角色”参与的合同
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            Long supplyEntId = Long.valueOf(req.getSupplyEntId());
            log.debug("应用供应方过滤条件: supplyEntId = {}", supplyEntId);

            Set<Long> supplyContractIds = units.stream()
                    .filter(unit -> Objects.equals(unit.getEntId(), supplyEntId))
                    // 必须明确 unitType 为 SUPPLIER (供应方)
                    .filter(unit -> Objects.equals(unit.getUnitType(), CooperateTypeEnum.SUPPLIER.getCode()))
                    .map(KwcContractTradeUnit::getContractId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            
            // 取交集
            int beforeSize = contractIds.size();
            contractIds.retainAll(supplyContractIds);
            log.debug("供应方过滤后剩余合同数量: {} (原数量: {})", contractIds.size(), beforeSize);
        }

        log.info("最终构建的合同ID集合大小: {}, entId: {}, purchaseEntId: {}, supplyEntId: {}", 
                contractIds.size(), entId, req.getPurchaseEntId(), req.getSupplyEntId());
        return contractIds;
    }

    private long countQueryTradeListByPage(QueryTradeReq req) {
        Long entId;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getEntId())) {
            entId = Long.valueOf(req.getEntId());
        } else {
            entId = LoginUserHolder.getEntId();
        }
        Set<Long> entIds = Sets.newHashSet();
        entIds.add(entId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
            entIds.add(Long.valueOf(req.getPurchaseEntId()));
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            entIds.add(Long.valueOf(req.getSupplyEntId()));
        }
        Set<Long> contractIds = buildTradeQueryContractIds(entId, req, entIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
            return 0L;
        }
        // 不分页，获取完整数据用于计算总数
        List<KwcContractTrade> records = kwcContractTradeRepository.queryTradeListByPageList(
                req.getContractCode(),
                req.getContractName(),
                req.getSupplementCode(),
                contractIds, req.getStatus(), req.getDispatchWay(), 0, 0);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return 0L;
        }
        DataPermissionDTO perm = fetchDataPermissionForCurrentUser();
        records = filterTradeContractsByPermission(records, perm);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return 0L;
        }
        entIds.addAll(records.stream().map(KwcContractTrade::getEntId).collect(Collectors.toSet()));
        List<EntTypeResDto> ents = remoteSystemService.queryEntTypeByIds(entIds);
        Map<Long, EntTypeResDto> entIdAndEntMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(ents)) {
            entIdAndEntMap =
                    ents.stream().collect(Collectors.toMap(EntTypeResDto::getEntId, Function.identity(), (v1, v2) -> v1));
        }
        EntTypeResDto entTypeResDto = entIdAndEntMap.getOrDefault(entId, new EntTypeResDto());
        List<KwcContractTrade> contractTrades = Lists.newArrayList();
        List<KwcContractTrade> contractTrades1 = Lists.newArrayList();
        if (entTypeResDto.getType().equals(EntTypeEnum.PURCHASER.getCode())) {
            List<Integer> statusList = Arrays.asList(ContractStatusEnum.SIGNED.getCode(), ContractStatusEnum.COMPLETE.getCode());
            Map<Long, EntTypeResDto> finalEntIdAndEntMap1 = entIdAndEntMap;

            records.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap1.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode()) && statusList.contains(record.getStatus())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        if (entTypeResDto.getType().equals(EntTypeEnum.SUPPLIER.getCode())) {
            Map<Long, EntTypeResDto> finalEntIdAndEntMap = entIdAndEntMap;
            records.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode()) && !Objects.equals(record.getStatus(), ContractStatusEnum.CANNEL.getCode())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        contractTrades.addAll(contractTrades1);
        records = contractTrades;
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return 0L;
        }

        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())
                || org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            Set<Long> tradeContractIds = records.stream().map(KwcContractTrade::getId).collect(Collectors.toSet());
            List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractIds(tradeContractIds);
            Map<String, KwcContractTradeUnit> contractUnitTypeKeyAndUnitMap = Maps.newHashMap();
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tradeUnits)) {
                contractUnitTypeKeyAndUnitMap = tradeUnits.stream()
                        .peek(x -> x.setContractIdUniTypeKey(x.getContractId() + "-" + x.getUnitType()))
                        .collect(Collectors.toMap(KwcContractTradeUnit::getContractIdUniTypeKey, Function.identity(), (v1
                                , v2) -> v1));
            }
            Map<String, KwcContractTradeUnit> finalContractUnitTypeKeyAndUnitMap = contractUnitTypeKeyAndUnitMap;
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
                records = records.stream().filter(record -> {
                    KwcContractTradeUnit purchaseEnt =
                            finalContractUnitTypeKeyAndUnitMap.getOrDefault(record.getId() + "-" + CooperateTypeEnum.PURCHASER.getCode(),
                                    new KwcContractTradeUnit());
                    return org.apache.commons.lang3.StringUtils.equals(String.valueOf(purchaseEnt.getEntId()), req.getPurchaseEntId());
                }).collect(Collectors.toList());
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
                records = records.stream().filter(record -> {
                    KwcContractTradeUnit provideEnt =
                            finalContractUnitTypeKeyAndUnitMap.getOrDefault(record.getId() + "-" + CooperateTypeEnum.SUPPLIER.getCode(),
                                    new KwcContractTradeUnit());
                    return org.apache.commons.lang3.StringUtils.equals(String.valueOf(provideEnt.getEntId()), req.getSupplyEntId());
                }).collect(Collectors.toList());
            }
        }
        return records.size();
    }


    public List<TradeEntInfoResVo> queryTradeEntList(TradeEntListQueryFeignDto queryFeignDto) {
        List<TradeEntInfoResVo> resVos = new ArrayList<>();
        Long entId = queryFeignDto.getCurEntId();
        Set<Long> entIds = Sets.newHashSet();
        entIds.add(entId);
        Set<Long> contractIds = null;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(entIds)) {
            List<KwcContractTradeUnit> units = kwcContractTradeUnitRepository.queryByEntIds(entIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
                contractIds = units.stream()
                        .map(KwcContractTradeUnit::getContractId)
                        .collect(Collectors.toSet());
            }
        }
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
            return Collections.emptyList();
        }
        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractIdsAndEntType(contractIds, queryFeignDto.getTradeEntType());
        for (KwcContractTradeUnit tradeUnit : tradeUnits) {
            TradeEntInfoResVo resVo = new TradeEntInfoResVo();
            resVo.setEntId(tradeUnit.getEntId());
            resVo.setEntName(tradeUnit.getFirmName());
            resVos.add(resVo);
        }
        return resVos;
    }

    /**
     * 查询销售报表商品列表
     * 范围为与当前公司存在合同（含已结束）的所有商品
     *
     * @param queryDto 查询参数
     * @return 商品列表
     */
    public List<SalesReportGoodsResVo> querySalesReportGoodsList(SalesReportGoodsQueryDto queryDto) {
        List<SalesReportGoodsResVo> resVos = new ArrayList<>();
        Long entId = queryDto.getCurEntId();

        Set<Long> entIds = Sets.newHashSet();
        entIds.add(entId);

        Set<Long> contractIds = null;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(entIds)) {
            List<KwcContractTradeUnit> units = kwcContractTradeUnitRepository.queryByEntIds(entIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
                contractIds = units.stream()
                        .map(KwcContractTradeUnit::getContractId)
                        .collect(Collectors.toSet());
            }
        }

        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)) {
            return Collections.emptyList();
        }

        List<KwcContractTradeGoods> tradeGoods = kwcContractTradeGoodsRepository.queryByContractIds(contractIds);

        // 提取所有商品ID
        Set<Long> goodsIds = tradeGoods.stream()
                .map(KwcContractTradeGoods::getGoodsId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 通过GoodsInfoService获取商品信息
        Map<Long, KwpGoods> goodsMap = new HashMap<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(goodsIds)) {
            Map<Long, KwpGoods> goodsByIds = goodsInfoService.getGoodsByIds(new ArrayList<>(goodsIds));
            if (goodsByIds != null) {
                goodsMap.putAll(goodsByIds);
            }
        }

        Map<Long, SalesReportGoodsResVo> resultMap = new java.util.LinkedHashMap<>();
        for (KwcContractTradeGoods goods : tradeGoods) {
            Long goodsId = goods.getGoodsId();
            if (goodsId == null) {
                continue;
            }

            KwpGoods kwpGoods = goodsMap.get(goodsId);
            if (kwpGoods == null) {
                continue;
            }

            String name = kwpGoods.getName();

            if (!resultMap.containsKey(goodsId)) {
                SalesReportGoodsResVo resVo = new SalesReportGoodsResVo();
                resVo.setGoodsId(goodsId);
                resVo.setGoodsName(name);
                resultMap.put(goodsId, resVo);
            }
        }

        resVos.addAll(resultMap.values());
        return resVos;
    }

    @NotNull
    private static QueryListResVo getQueryListResVo(KwcContractTrade t,
                                                    Map<String, KwcContractTradeUnit> finalContractUnitTypeKeyAndUnitMap,
                                                    Map<Long, KwcContractTrade> finalPidIdAndTradeMap,
                                                    Map<Long, UserCacheResDto> longUserCacheResDtoMap,
                                                    Map<Long, RWaybillSubOrderVo> tradeOrderIdAndWaybillMap,
                                                    Map<Long, TradeOrderContractVo> contractIdAndContractMap,
                                                    Map<Long, KwcContractTradeGoods> goodsIdAndGoodsMap) {
        QueryListResVo queryListResVo = new QueryListResVo();
        queryListResVo.setId(t.getId());
        queryListResVo.setStatus(t.getStatus());
        queryListResVo.setStatusName(ContractStatusEnum.getNameByCode(t.getStatus()));
        queryListResVo.setDispatchWay(t.getDispatchWay());
        queryListResVo.setDispatchWayDesc(DispatchWayEnums.getDesc(t.getDispatchWay()));

        KwcContractTradeUnit purchaseEnt = finalContractUnitTypeKeyAndUnitMap.getOrDefault(t.getId() + "-" + CooperateTypeEnum.PURCHASER.getCode(),
                new KwcContractTradeUnit());
        queryListResVo.setPurchaseEntId(String.valueOf(purchaseEnt.getEntId()));
        queryListResVo.setPurchaseEntName(purchaseEnt.getFirmName());
        KwcContractTradeUnit provideEnt =
                finalContractUnitTypeKeyAndUnitMap.getOrDefault(t.getId() + "-" + CooperateTypeEnum.SUPPLIER.getCode(),
                        new KwcContractTradeUnit());
        queryListResVo.setProvideEntId(String.valueOf(provideEnt.getEntId()));
        queryListResVo.setProvideEntName(provideEnt.getFirmName());
        //queryListResVo.setCheckedEntName();
        queryListResVo.setContractNo(t.getContractNo());
        queryListResVo.setContractName(t.getName());
        queryListResVo.setSigningWay(String.valueOf(t.getSigningWay()));
        queryListResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_TYPE.getType(), String.valueOf(t.getSigningWay())));
        queryListResVo.setUnloadWay(String.valueOf(t.getUnloadWay()));
        queryListResVo.setUnloadWayName(DictEnum.getLabel(DictTypeEnum.LOAD_UNLOAD_WAY.getType(),
                String.valueOf(t.getUnloadWay())));
        queryListResVo.setAmount(t.getAmount());
        TradeOrderContractVo tradeOrderContractVo = contractIdAndContractMap.getOrDefault(t.getId(), new TradeOrderContractVo());
        RWaybillSubOrderVo subOrderVo = tradeOrderIdAndWaybillMap.getOrDefault(tradeOrderContractVo.getTOrderId(), new RWaybillSubOrderVo());
        List<RWaybillSubOrderVo.BillSubOrder> subOrders = subOrderVo.getSubOrders();
        BigDecimal unloadQty = BigDecimal.ZERO;
        BigDecimal performedAmountMoney = BigDecimal.ZERO;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(subOrders)) {
            if (Objects.equals(t.getUnloadWay(), Integer.parseInt(DictEnum.LOAD_UNLOAD_WAY_1.getValue()))) {
                unloadQty = subOrders.stream()
                        .filter(x -> Arrays.asList(CarWaybillV1Enum.COMPLETION_LOADING.getCode(), CarWaybillV1Enum.COMPLETED.getCode())
                                .contains(x.getStatus()))
                        .map(RWaybillSubOrderVo.BillSubOrder::getLoadAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
            } else {
                unloadQty = subOrders.stream()
                        .filter(x -> Objects.equals(x.getStatus(), CarWaybillV1Enum.COMPLETED.getCode()))
                        .map(RWaybillSubOrderVo.BillSubOrder::getUnloadAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
            }

            performedAmountMoney = subOrders.stream()
                    .filter(x -> Objects.nonNull(x.getUnloadAmount()))
                    .map(x -> {
                        KwcContractTradeGoods orDefault = goodsIdAndGoodsMap.getOrDefault(x.getGoodId(), new KwcContractTradeGoods());
                        BigDecimal price = Optional.ofNullable(orDefault).map(KwcContractTradeGoods::getPrice).orElse(BigDecimal.ZERO);
                        return x.getUnloadAmount().multiply(price);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        queryListResVo.setPerformedAmount(unloadQty.setScale(2, RoundingMode.HALF_UP));

        queryListResVo.setPerformedAmountMoney(performedAmountMoney.setScale(2, RoundingMode.HALF_UP));
        queryListResVo.setContractPid(t.getContractPid());
        KwcContractTrade parentTrade = finalPidIdAndTradeMap.getOrDefault(t.getContractPid(),
                new KwcContractTrade());
        queryListResVo.setContractPname(parentTrade.getName());
        UserCacheResDto userCacheResDto = longUserCacheResDtoMap.getOrDefault(t.getCreateBy(), new UserCacheResDto());
        queryListResVo.setInitiatorId(t.getCreateBy());
        queryListResVo.setInitiateName(userCacheResDto.getName());
        if (Objects.nonNull(userCacheResDto.getEntInfo())) {
            queryListResVo.setInitiateEntName(userCacheResDto.getEntInfo().getFirmName());
        }
        queryListResVo.setCreateTime(t.getCreateTime());
        queryListResVo.setStartTime(t.getStartTime());
        queryListResVo.setUpdateTime(t.getUpdateTime());
        if (Objects.nonNull(t.getEndTime())) {
            queryListResVo.setEndTime(t.getEndTime());
            String endDate = DateUtils.format(t.getEndTime(), DateUtils.DATE_PATTERN);
            if (org.apache.commons.lang3.StringUtils.equals(endDate, "9999-12-30")) {
                queryListResVo.setEndTime(null);
            }
        }
        queryListResVo.setInitiateTime(t.getCreateTime());
        queryListResVo.setRemark(t.getRemark());
        queryListResVo.setSignTime(t.getSignTime());
        return queryListResVo;
    }


    public List<ContractLogisticsOrderResDto> queryContractLogisticsOrder(LogisticsOrderDto logisticsOrderDto) {
        log.info("查询物流合同请求：{}", JSON.toJSONString(logisticsOrderDto));

        if (Objects.isNull(logisticsOrderDto.getGoodsId())) {
            throw new BusinessException("商品id不能为空！");
        }
        if (Objects.isNull(logisticsOrderDto.getEntId())) {
            throw new BusinessException("托运方企业id不能为空！");
        }
        //通过托运企业查询物流公司
        List<KwcContractLogisticsUnit> contractLogistics =
                kwcContractLogisticsUnitRepository.queryByEntId(logisticsOrderDto.getEntId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractLogistics)) {
            return Collections.emptyList();
        }
        //物流订单合id
        Set<Long> logTradeContractIds = contractLogistics.stream()
                .map(KwcContractLogisticsUnit::getContractId).collect(Collectors.toSet());

        //查询商品信息
        List<KwcContractLogisticsGoods> kwcContractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByLogIdsAndGoodsId(logTradeContractIds,
                logisticsOrderDto.getGoodsId());
        Map<Long, KwcContractLogisticsGoods> contractLogisticsGoodsMap = Maps.newHashMap();
        Set<Long> goodsContractIds = new HashSet<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwcContractLogisticsGoods)) {
            contractLogisticsGoodsMap = kwcContractLogisticsGoods.stream()
                    .collect(Collectors.toMap(KwcContractLogisticsGoods::getContractId,
                            Function.identity(), (x, y) -> x));
            goodsContractIds = kwcContractLogisticsGoods.stream()
                    .map(KwcContractLogisticsGoods::getContractId)
                    .collect(Collectors.toSet());
        }

        //查询物流订单  如果是通用价格不为空的不能过滤掉
        List<KwcContractLogistics> logistics = contractLogisticsRepository.queryByLogisticContractIds(logTradeContractIds);
        Set<Long> finalGoodsContractIds = goodsContractIds;
        logistics = logistics.stream().filter(x-> finalGoodsContractIds.contains(x.getId()) || Objects.nonNull(x.getCommonPrice()))
                .distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(logistics)) {
            return Collections.emptyList();
        }
        Date date = new Date();
        logistics = logistics.stream()
                .peek(log -> {
                    if (Objects.isNull(log.getEndTime())) {
                        LocalDate localDate = LocalDate.of(9999, 12, 30);
                        Date date1 = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
                        log.setEndTime(date1);
                    }
                })
                .filter(log -> Objects.nonNull(log.getStartTime()) && Objects.nonNull(log.getEndTime()))
                .filter(log -> Objects.equals(log.getStatus(), ContractStatusEnum.SIGNED.getCode())
                        && log.getStartTime().before(date) && log.getEndTime().after(date))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(logistics)) {
            return Collections.emptyList();
        }
        //查询企业
        List<KwcContractLogisticsUnit> units = kwcContractLogisticsUnitRepository.queryByContractIds(logTradeContractIds);
        //物流订单和类型组成唯一key
        Map<String, KwcContractLogisticsUnit> contractLogisticsMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
            contractLogisticsMap = units.stream()
                    .collect(Collectors.toMap(c -> c.getContractId() + "_" + c.getUnitType(),
                            Function.identity(), (x, y) -> x));
        }
        Map<String, KwcContractLogisticsUnit> finalContractLogisticsMap = contractLogisticsMap;
        Map<Long, KwcContractLogisticsGoods> finalContractLogisticsGoodsMap = contractLogisticsGoodsMap;
        List<ContractLogisticsOrderResDto> collect = logistics.stream()
                .map(log -> getContractLogisticsOrderResDto(log, finalContractLogisticsMap, finalContractLogisticsGoodsMap))
                .collect(Collectors.toList());
        // 贸易合同 按装货量 并且买家托运时
        Long tradeContractId = logisticsOrderDto.getTradeContractId();

        if (Objects.nonNull(tradeContractId)) {
            KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(tradeContractId);
            if (Objects.nonNull(kwcContractTrade)) {
                if (Objects.equals(kwcContractTrade.getConsignment(), 1) && Objects.equals(kwcContractTrade.getUnloadWay(), 1)) {
                    ContractLogisticsOrderResDto contractLogisticsOrderResDto = new ContractLogisticsOrderResDto();
                    contractLogisticsOrderResDto.setId(0L);
                    contractLogisticsOrderResDto.setContactName("平台默认物流");
                    contractLogisticsOrderResDto.setContractNo("MRWL");
                    contractLogisticsOrderResDto.setSigningWay(0);
                    contractLogisticsOrderResDto.setSigningWayName("");
                    contractLogisticsOrderResDto.setStatus(0);
                    contractLogisticsOrderResDto.setStatusName("");
                    contractLogisticsOrderResDto.setConsignEntId(0L);
                    contractLogisticsOrderResDto.setConsignEntName("");
                    contractLogisticsOrderResDto.setConsignEntPhone("");
                    contractLogisticsOrderResDto.setConsignEntContactId(0L);
                    contractLogisticsOrderResDto.setConsignEntContact("");
                    contractLogisticsOrderResDto.setAcceptCarriageEntId(0L);
                    contractLogisticsOrderResDto.setAcceptCarriageEntPhone("");
                    contractLogisticsOrderResDto.setAcceptCarriageEntContactId(0L);
                    contractLogisticsOrderResDto.setAcceptCarriageEntContact("");
                    contractLogisticsOrderResDto.setAcceptCarriageEntName("");
                    contractLogisticsOrderResDto.setPrice(new BigDecimal("0"));
                    collect.add(0, contractLogisticsOrderResDto);
                }
            }
        }
        return collect;

    }

    @NotNull
    private static ContractLogisticsOrderResDto getContractLogisticsOrderResDto(KwcContractLogistics log, Map<String, KwcContractLogisticsUnit> contractLogisticsMap, Map<Long, KwcContractLogisticsGoods> contractLogisticsGoodsMap) {
        ContractLogisticsOrderResDto contractLogisticsOrderResDto = new ContractLogisticsOrderResDto();
        contractLogisticsOrderResDto.setId(log.getId());
        contractLogisticsOrderResDto.setContactName(log.getName());
        contractLogisticsOrderResDto.setContractNo(log.getContractNo());
        contractLogisticsOrderResDto.setSigningWay(log.getSigningWay());
        contractLogisticsOrderResDto.setStatus(log.getStatus());
        KwcContractLogisticsUnit consignEnt = contractLogisticsMap.getOrDefault(log.getId() + "_" + CooperateTypeEnum.CONSIGN.getCode(),
                new KwcContractLogisticsUnit());
        KwcContractLogisticsUnit acceptCarriageEnt = contractLogisticsMap.getOrDefault(log.getId() + "_" + CooperateTypeEnum.CARRIAGE.getCode(),
                new KwcContractLogisticsUnit());
        contractLogisticsOrderResDto.setConsignEntId(consignEnt.getEntId());
        contractLogisticsOrderResDto.setConsignEntName(consignEnt.getFirmName());
        contractLogisticsOrderResDto.setConsignEntPhone(consignEnt.getPhone());
        contractLogisticsOrderResDto.setConsignEntContactId(consignEnt.getContactsId());
        contractLogisticsOrderResDto.setConsignEntContact(consignEnt.getContacts());
        contractLogisticsOrderResDto.setAcceptCarriageEntId(acceptCarriageEnt.getEntId());
        contractLogisticsOrderResDto.setAcceptCarriageEntName(acceptCarriageEnt.getFirmName());
        contractLogisticsOrderResDto.setAcceptCarriageEntPhone(acceptCarriageEnt.getPhone());
        contractLogisticsOrderResDto.setAcceptCarriageEntContactId(acceptCarriageEnt.getContactsId());
        contractLogisticsOrderResDto.setAcceptCarriageEntContact(acceptCarriageEnt.getContacts());
        KwcContractLogisticsGoods goods = contractLogisticsGoodsMap.getOrDefault(log.getId(),
                new KwcContractLogisticsGoods());
        contractLogisticsOrderResDto.setPrice(StringUtils.isNotBlank(goods.getPrice()) ? goods.getPrice() : log.getCommonPrice());
        return contractLogisticsOrderResDto;
    }


    public List<ContractTradeOrderInfo> queryContractTradeOrder(ContractTradeOrderDto contractTradeOrderDto) {
        log.info("查询贸易合同订单，请求：{}", JSON.toJSONString(contractTradeOrderDto));
        checkParam(contractTradeOrderDto.getGoodsId(), contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType());
        //查询贸易合同企业信息
        List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByEntIdAndUnitType(contractTradeOrderDto.getEntId(),
                contractTradeOrderDto.getEntType());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits)) {
            log.info("查询贸易合同订单，未查询到企业关联合同，entId:{}，entType:{}，goodsId:{}",
                    contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType(), contractTradeOrderDto.getGoodsId());
            return List.of();
        }
        Set<Long> contractIds =
                tradeUnits.stream().map(KwcContractTradeUnit::getContractId).collect(Collectors.toSet());
        log.info("查询贸易合同订单，企业关联合同数量:{}，entId:{}，entType:{}，contractIds:{}",
                tradeUnits.size(), contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType(), JSON.toJSONString(contractIds));

        List<KwcContractTradeUnit> tradeUnits1 = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeUnits1)) {
            log.info("查询贸易合同订单，未查询到合同双方企业信息，contractIds:{}", JSON.toJSONString(contractIds));
            return List.of();
        }
        log.info("查询贸易合同订单，合同企业信息数量:{}，contractIds:{}", tradeUnits1.size(), JSON.toJSONString(contractIds));
        Map<String, KwcContractTradeUnit> conTractTradeUnitMap =
                tradeUnits1.stream().collect(Collectors.toMap(x -> x.getContractId() +
                                "_" + x.getUnitType(), Function.identity(),
                        (x, y) -> x));
        contractIds = tradeUnits1.stream()
                .filter(x -> Objects.equals(x.getEntId(), LoginUserHolder.getEntId()) && Objects.equals(x.getUnitType(),
                        2))
                .map(KwcContractTradeUnit::getContractId)
                .collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(contractIds)) {
            log.info("该企业下没有贸易合同，企业id:{}", contractTradeOrderDto.getEntId());
            return Collections.emptyList();

        }
        //查询商品信息
        log.info("查询贸易合同订单，登录企业过滤后合同数量:{}，loginEntId:{}，contractIds:{}",
                contractIds.size(), LoginUserHolder.getEntId(), JSON.toJSONString(contractIds));
        List<KwcContractTradeGoods> kwcContractGoods = kwcContractTradeGoodsRepository.queryByContractIdsAndGoodsId(contractIds,
                contractTradeOrderDto.getGoodsId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwcContractGoods)) {
            log.info("查询贸易合同订单，未查询到合同商品信息，goodsId:{}，contractIds:{}",
                    contractTradeOrderDto.getGoodsId(), JSON.toJSONString(contractIds));
            return Collections.emptyList();
        }
        log.info("查询贸易合同订单，合同商品数量:{}，goodsId:{}", kwcContractGoods.size(), contractTradeOrderDto.getGoodsId());
        Map<Long, KwcContractTradeGoods> contractGoodsMap = kwcContractGoods.stream()
                .collect(Collectors.toMap(KwcContractTradeGoods::getContractId, Function.identity(), (x, y) -> x));
        //只查询已签约的
        Set<Long> contractIdList = kwcContractGoods.stream()
                .filter(x -> Objects.equals(x.getStatus(), ContractStatusEnum.SIGNED.getCode()))
                .map(KwcContractTradeGoods::getContractId)
                .collect(Collectors.toSet());
        //查询贸易合同
        if (CollectionUtils.isEmpty(contractIdList)) {
            log.info("该企业下没有已签约的贸易合同，企业id:{}", contractTradeOrderDto.getEntId());
            return Collections.emptyList();
        }
        log.info("查询贸易合同订单，已签约商品关联合同数量:{}，contractIds:{}",
                contractIdList.size(), JSON.toJSONString(contractIdList));
        List<KwcContractTrade> kwcContractTrades = kwcContractTradeRepository.findByContractIds(contractIdList);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwcContractTrades)) {
            log.info("查询贸易合同订单，未查询到合同信息，contractIds:{}", JSON.toJSONString(contractIdList));
            return Collections.emptyList();
        }
        kwcContractTrades = kwcContractTrades.stream()
                .filter(x -> Objects.equals(x.getStatus(), ContractStatusEnum.SIGNED.getCode()))
                .collect(Collectors.toList());
        log.info("查询贸易合同订单，合同状态过滤后数量:{}", kwcContractTrades.size());
        List<ContractTradeOrderInfo> resultList = kwcContractTrades.stream()
                .map(x -> getContractTradeOrderInfo(x, conTractTradeUnitMap, contractTradeOrderDto.getEntType(), contractGoodsMap))
                .collect(Collectors.toList());
        log.info("查询贸易合同订单完成，返回数量:{}，entId:{}，entType:{}，goodsId:{}",
                resultList.size(), contractTradeOrderDto.getEntId(), contractTradeOrderDto.getEntType(), contractTradeOrderDto.getGoodsId());
        return resultList;
    }

    private static void checkParam(Long contractTradeOrderDto, Long contractTradeOrderDto1, Integer contractTradeOrderDto2) {
        if (Objects.isNull(contractTradeOrderDto) && Objects.equals(contractTradeOrderDto2, 1)) {
            throw new BusinessException("商品id不能为空！");
        }
        if (Objects.isNull(contractTradeOrderDto1)) {
            throw new BusinessException("托运方企业id不能为空！");
        }
        if (Objects.isNull(contractTradeOrderDto2)) {
            throw new BusinessException("企业类型不能为空！");
        }
    }

    @NotNull
    private static ContractTradeOrderInfo getContractTradeOrderInfo(KwcContractTrade c, Map<String,
            KwcContractTradeUnit> conTractTradeUnitMap, Integer entType, Map<Long, KwcContractTradeGoods> contractGoodsMap) {
        ContractTradeOrderInfo contractTradeOrderInfo = new ContractTradeOrderInfo();
        contractTradeOrderInfo.setId(c.getId());
        KwcContractTradeUnit unit = conTractTradeUnitMap.getOrDefault(c.getId() + "_" + entType,
                new KwcContractTradeUnit());
        contractTradeOrderInfo.setEntId(unit.getEntId());
        contractTradeOrderInfo.setContractNo(c.getContractNo());
        contractTradeOrderInfo.setName(c.getName());
        contractTradeOrderInfo.setSigningWay(c.getSigningWay());
        contractTradeOrderInfo.setTrading(c.getTrading());
        contractTradeOrderInfo.setStartTime(c.getStartTime());
        contractTradeOrderInfo.setEndTime(c.getEndTime());

        contractTradeOrderInfo.setPerformedAmount(c.getPerformedAmount());
        contractTradeOrderInfo.setSigningUrl(c.getSigningUrl());
        contractTradeOrderInfo.setSignedUrl(c.getSignedUrl());
        contractTradeOrderInfo.setSigningNo(c.getSigningNo());
        contractTradeOrderInfo.setContractPid(c.getContractPid());
        contractTradeOrderInfo.setRemark(c.getRemark());
        contractTradeOrderInfo.setStatus(c.getStatus());
        contractTradeOrderInfo.setCreateBy(c.getCreateBy());
        contractTradeOrderInfo.setCreateTime(c.getCreateTime());
        contractTradeOrderInfo.setUpdateBy(c.getUpdateBy());
        contractTradeOrderInfo.setUpdateTime(c.getUpdateTime());
        contractTradeOrderInfo.setDelFlag(c.getDelFlag());
        contractTradeOrderInfo.setBusinessId(c.getBusinessId());
        contractTradeOrderInfo.setSettlement(c.getSettlement());
        contractTradeOrderInfo.setConsignment(c.getConsignment());
        contractTradeOrderInfo.setUnloadWay(c.getUnloadWay());
        contractTradeOrderInfo.setSalesmanId(c.getSalesmanId());
        contractTradeOrderInfo.setSalesmanPhone(c.getSalesmanPhone());
        KwcContractTradeGoods kwcContractTradeGoods = contractGoodsMap.getOrDefault(c.getId(), new KwcContractTradeGoods());
        contractTradeOrderInfo.setSignPrice(Objects.nonNull(kwcContractTradeGoods.getPrice()) ? kwcContractTradeGoods.getPrice() : new BigDecimal("-1"));
        contractTradeOrderInfo.setAmount(Objects.isNull(kwcContractTradeGoods.getAmount()) ? new BigDecimal("-1") : kwcContractTradeGoods.getAmount());
        return contractTradeOrderInfo;
    }

    public ContractStatusCountResp queryTradeContractStatusCount(QueryListReqVo req) {
        log.info("查询贸易合同订单状态统计");

        List<ContractStatusEnum> statusEnums = Arrays.stream(ContractStatusEnum.values())
                .sorted(Comparator.comparing(ContractStatusEnum::getCode))
                .collect(Collectors.toList());
        ContractStatusCountResp contractStatusCountResp = new ContractStatusCountResp();
        contractStatusCountResp.setTotalNum("0");
        Long entId;
        if (Objects.nonNull(req.getEntId())) {
            entId = req.getEntId();
        } else {
            entId = LoginUserHolder.getEntId();
        }
        // Integer type =null;
        Set<Long> entIds = Sets.newHashSet();
        entIds.add(entId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getPurchaseEntId())) {
            //查询企业 信息
            entIds.add(Long.valueOf(req.getPurchaseEntId()));
            // type=CooperateTypeEnum.PURCHASER.getCode();
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getSupplyEntId())) {
            entIds.add(Long.valueOf(req.getSupplyEntId()));
            // type=CooperateTypeEnum.SUPPLIER.getCode();
        }
        Set<Long> contractIds = null;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(entIds)) {
            List<KwcContractTradeUnit> units = kwcContractTradeUnitRepository.queryByEntIds(entIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
                Set<Long> contractList = units.stream().filter(x -> Objects.equals(x.getEntId(), entId))
                        .map(KwcContractTradeUnit::getContractId)
                        .collect(Collectors.toSet());
                contractIds = units.stream()
                        .map(KwcContractTradeUnit::getContractId)
                        .filter(contractList::contains)
                        .collect(Collectors.toSet());
            }
        }
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractIds)
                && (!org.apache.commons.lang3.StringUtils.isAllBlank(req.getPurchaseEntId(), req.getSupplyEntId()) || Objects.nonNull(entId))) {
            Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap = new HashMap<>();
            List<ContractStatusCountResp.ContractStatusCount> statusCounts = statusEnums.stream()
                    .map(x -> getContractStatusCount(x, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            contractStatusCountResp.setContractStatusInfo(statusCounts);
            return contractStatusCountResp;
        }

        List<KwcContractTrade> kwcContractTrades = kwcContractTradeRepository.queryTradeListByPageList(
                req.getContractCode(),
                req.getContractName(),
                req.getSupplementCode(),
                contractIds, req.getStatus(), req.getDispatchWay(), 0, 0);

        // List<KwcContractTrade> kwcContractTrades = kwcContractTradeRepository.queryTradeListByPageList(LoginUserHolder.getEntId());

        if (CollectionUtils.isEmpty(kwcContractTrades)) {
            Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap = new HashMap<>();
            List<ContractStatusCountResp.ContractStatusCount> statusCounts = statusEnums.stream()
                    .map(x -> getContractStatusCount(x, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            contractStatusCountResp.setContractStatusInfo(statusCounts);
            return contractStatusCountResp;
        }
        DataPermissionDTO dataPerm = fetchDataPermissionForCurrentUser();
        kwcContractTrades = filterTradeContractsByPermission(kwcContractTrades, dataPerm);
        if (CollectionUtils.isEmpty(kwcContractTrades)) {
            Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap = new HashMap<>();
            List<ContractStatusCountResp.ContractStatusCount> statusCounts = statusEnums.stream()
                    .map(x -> getContractStatusCount(x, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            contractStatusCountResp.setContractStatusInfo(statusCounts);
            return contractStatusCountResp;
        }
        entIds.addAll(kwcContractTrades.stream().map(KwcContractTrade::getEntId).collect(Collectors.toSet()));
        List<EntTypeResDto> ents = remoteSystemService.queryEntTypeByIds(entIds);
        Map<Long, EntTypeResDto> entIdAndEntMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(ents)) {
            entIdAndEntMap =
                    ents.stream().collect(Collectors.toMap(EntTypeResDto::getEntId, Function.identity(), (v1, v2) -> v1));
        }
        //如果登录方是采购方，创建方是提供方，那么采购方只能看到已经签约的合同
        EntTypeResDto entTypeResDto = entIdAndEntMap.getOrDefault(entId, new EntTypeResDto());
        //如果登录方是采购商，创建方是供应方，那么采购商只能看到已经签约的合同
        List<KwcContractTrade> contractTrades = Lists.newArrayList();
        List<KwcContractTrade> contractTrades1 = Lists.newArrayList();
        if (entTypeResDto.getType().equals(EntTypeEnum.PURCHASER.getCode())) {

            List<Integer> statusList = Arrays.asList(ContractStatusEnum.SIGNED.getCode(), ContractStatusEnum.COMPLETE.getCode());
            Map<Long, EntTypeResDto> finalEntIdAndEntMap1 = entIdAndEntMap;

            kwcContractTrades.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap1.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode()) && statusList.contains(record.getStatus())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        //如果登录方是供应方，创建方是采购方，那么供应方不能看到已作废的 合同
        if (entTypeResDto.getType().equals(EntTypeEnum.SUPPLIER.getCode())) {
            Map<Long, EntTypeResDto> finalEntIdAndEntMap = entIdAndEntMap;
            kwcContractTrades.forEach(record -> {
                EntTypeResDto orDefault = finalEntIdAndEntMap.getOrDefault(record.getEntId(), new EntTypeResDto());
                if (Objects.equals(orDefault.getType(), EntTypeEnum.PURCHASER.getCode()) && !Objects.equals(record.getStatus(), ContractStatusEnum.CANNEL.getCode())) {
                    contractTrades.add(record);
                } else if (Objects.equals(orDefault.getType(), EntTypeEnum.SUPPLIER.getCode())) {
                    contractTrades1.add(record);
                }
            });
        }
        contractTrades.addAll(contractTrades1);
        kwcContractTrades = contractTrades;
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwcContractTrades)) {
            Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap = new HashMap<>();
            List<ContractStatusCountResp.ContractStatusCount> statusCounts = statusEnums.stream()
                    .map(x -> getContractStatusCount(x, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            contractStatusCountResp.setContractStatusInfo(statusCounts);
            return contractStatusCountResp;
        }
        Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap = kwcContractTrades.stream().collect(Collectors.groupingBy(KwcContractTrade::getStatus));
        return getContractStatusCountResp(statusEnums, statusAndLogOrdersMap, contractStatusCountResp, kwcContractTrades);
    }

    @NotNull
    private static ContractStatusCountResp getContractStatusCountResp(List<ContractStatusEnum> statusEnums, Map<Integer, List<KwcContractTrade>> statusAndLogOrdersMap, ContractStatusCountResp contractStatusCountResp, List<KwcContractTrade> kwcContractTrades) {
        List<ContractStatusCountResp.ContractStatusCount> statusCounts = statusEnums.stream()
                .map(x -> getContractStatusCount(x, statusAndLogOrdersMap))
                .collect(Collectors.toList());
        contractStatusCountResp.setContractStatusInfo(statusCounts);
        contractStatusCountResp.setTotalNum(String.valueOf(kwcContractTrades.size()));
        return contractStatusCountResp;
    }

    private static ContractStatusCountResp.ContractStatusCount getContractStatusCount(ContractStatusEnum x, Map<Integer, List<KwcContractTrade>> finalStatusAndLogOrdersMap1) {
        ContractStatusCountResp.ContractStatusCount contractStatusCount = new ContractStatusCountResp.ContractStatusCount();
        contractStatusCount.setOrderStatus(String.valueOf(x.getCode()));
        contractStatusCount.setOrderStatusDesc(x.getName());
        contractStatusCount.setOrderNum(String.valueOf(finalStatusAndLogOrdersMap1.getOrDefault(x.getCode(), new ArrayList<>()).size()));
        return contractStatusCount;
    }

    public List<Long> queryTradeContractInfo(Long contractId) {
        return kwcContractTradeMapper.selectByContract(contractId);
    }


    /**
     * 查询同产品和同托运企业是否存在自动派车合同
     *
     * @param entId    托运企业
     * @param goodsIds 商品id集合
     * @return
     */
    public List<LogisticsEntDtoVO> queryAutoContractLogOrder(Long entId, List<Long> goodsIds) {
        log.info("查询满足贸易合合同供应企业和商品的自动派车的物流合同，企业id：{}, 商品id：{}", entId, JSON.toJSONString(goodsIds));
        if (Objects.isNull(entId)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "供应商企业id不能为空！");
        }
        if (CollectionUtils.isEmpty(goodsIds)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "商品id不能为空！");
        }

        //1. 查询供应商企业物流合同关联的unit信息
        List<KwcContractLogisticsUnit> contractLogisticsUnits = kwcContractLogisticsUnitRepository.queryByEntIdAndType(entId);
        if (CollectionUtils.isEmpty(contractLogisticsUnits)) {
            return Collections.emptyList();
        }
        Set<Long> unitContractIds = contractLogisticsUnits.stream().map(KwcContractLogisticsUnit::getContractId).collect(Collectors.toSet());

        //2. 查询自动派车物流合同主信息
        List<KwcContractLogistics> contractLogisticsList = contractLogisticsRepository.queryByIdsAndDispatch(unitContractIds);
        if (CollectionUtils.isEmpty(contractLogisticsList)) {
            return Collections.emptyList();
        }

        // 3. 拆分合同：通用价格>0的直接保留，通用价格=0的需要校验商品id
        List<Long> validContractIds = new ArrayList<>();
        List<Long> needCheckGoodsContractIds = new ArrayList<>();

        for (KwcContractLogistics contractLogistics : contractLogisticsList) {
            if (contractLogistics.getCommonPrice().compareTo(BigDecimal.ZERO) > 0) {
                //通用价格大于0，无需校验goodsIds
                validContractIds.add(contractLogistics.getId());
            } else {
                // 通用价格=0，需要校验商品
                needCheckGoodsContractIds.add(contractLogistics.getId());
            }
        }

        // 4. 处理需要校验商品的合同ID
        if (CollectionUtils.isNotEmpty(needCheckGoodsContractIds)) {
            //查询物流商品合同信息
            List<KwcContractLogisticsGoods> contractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByContractIds(unitContractIds);
            if (CollectionUtils.isNotEmpty(contractLogisticsGoods)) {
                // 按合同ID分组商品信息
                Map<Long, List<KwcContractLogisticsGoods>> logisticsGoodsMap = contractLogisticsGoods.stream().collect(Collectors.groupingBy(KwcContractLogisticsGoods::getContractId));
                for (Long contractId : needCheckGoodsContractIds) {
                    List<KwcContractLogisticsGoods> logisticsGoodList = logisticsGoodsMap.get(contractId);
                    // 提取当前合同下的所有商品ID
                    Set<Long> currentGoodsIds = logisticsGoodList.stream().map(KwcContractLogisticsGoods::getGoodsId).filter(Objects::nonNull).collect(Collectors.toSet());
                    // 校验目标商品ID是否全部包含
                    boolean isContains = goodsIds.stream().allMatch(currentGoodsIds::contains);
                    if (isContains) {
                        validContractIds.add(contractId);
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(validContractIds)) {
            return Collections.emptyList();
        }
        //过滤满足商品数据
        List<KwcContractLogistics> finalContractList = contractLogisticsList.stream()
                .filter(contract -> validContractIds.contains(contract.getId()))
                .collect(Collectors.toList());

        //过滤有效期合同
        List<KwcContractLogistics> filteredLogistics = finalContractList.stream().filter(Objects::nonNull)
                .filter(con -> con.getStartTime() != null)
                .filter(con -> {
                    return !con.getStartTime().after(new Date());
                }).collect(Collectors.toList());

        return toLogisticsEntDtoVO(entId, filteredLogistics);
    }

    /**
     * 参数转换
     *
     * @param contractLogisticsList
     * @return
     */
    private List<LogisticsEntDtoVO> toLogisticsEntDtoVO(Long supEntId, List<KwcContractLogistics> contractLogisticsList) {
        return contractLogisticsList.stream().filter(Objects::nonNull).map(log -> {
            LogisticsEntDtoVO vo = new LogisticsEntDtoVO();
            vo.setContractId(log.getId());
            vo.setContractNo(log.getContractNo());
            vo.setContractName(log.getName());
            vo.setContractSigningWay(String.valueOf(log.getSigningWay()));
            vo.setContractStatus(String.valueOf(log.getStatus()));
            vo.setStartTime(log.getStartTime());
            vo.setEndTime(log.getEndTime());
            vo.setCommonPrice(log.getCommonPrice());

            //承运企业信息
            TradeContractUnitDto unit = queryEntByContractId(log.getId());
            vo.setEntId(unit.getEntId());
            vo.setEntName(unit.getFirmName());
            vo.setContactsId(unit.getContactsId());
            vo.setContacts(unit.getContacts());
            vo.setPhone(unit.getPhone());

            //企业评分
            KwcContractLogisticsScore entScore = queryEntScoreByEntId(supEntId, unit.getEntId());
            vo.setScore(entScore.getScore());

            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 查询同产品和同托运企业是否存在手动派车合同
     *
     * @param entId   托运企业
     * @param goodsId 商品id集合
     * @return
     */
    public List<LogisticsEntDtoVO> queryContractLogOrder(Long entId, Long goodsId) {
        log.info("查询满足贸易合合同供应企业和商品的手动派车的物流合同，企业id：{}, 商品id：{}", entId, goodsId);
        if (Objects.isNull(entId)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "供应商企业id不能为空！");
        }
        if (goodsId == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "商品id不能为空！");
        }

        //1. 查询供应商企业物流合同信息
        List<KwcContractLogisticsUnit> contractLogisticsUnits = kwcContractLogisticsUnitRepository.queryByEntIdAndType(entId);
        if (CollectionUtils.isEmpty(contractLogisticsUnits)) {
            return Collections.emptyList();
        }
        Set<Long> unitContractIds = contractLogisticsUnits.stream().map(KwcContractLogisticsUnit::getContractId).collect(Collectors.toSet());

        //2. 查询手动派车物流合同主信息
        List<KwcContractLogistics> contractLogisticsList = contractLogisticsRepository.queryBycontractIdList(unitContractIds);
        if (CollectionUtils.isEmpty(contractLogisticsList)) {
            return Collections.emptyList();
        }

        // 3. 拆分合同：通用价格>0的直接保留，通用价格=0的需要校验商品id
        List<Long> validContractIds = new ArrayList<>();
        List<Long> needCheckGoodsContractIds = new ArrayList<>();

        for (KwcContractLogistics contractLogistics : contractLogisticsList) {
            if (contractLogistics.getCommonPrice().compareTo(BigDecimal.ZERO) > 0) {
                //通用价格大于0，无需校验goodsIds
                validContractIds.add(contractLogistics.getId());
            } else {
                // 通用价格=0，需要校验商品
                needCheckGoodsContractIds.add(contractLogistics.getId());
            }
        }

        // 4. 处理需要校验商品的合同ID
        if (CollectionUtils.isNotEmpty(needCheckGoodsContractIds)) {
            //查询物流商品合同信息
            List<KwcContractLogisticsGoods> contractLogisticsGoods = kwcContractLogisticsGoodsRepository.queryByContractIds(unitContractIds);
            if (CollectionUtils.isNotEmpty(contractLogisticsGoods)) {
                // 按合同ID分组商品信息
                Map<Long, List<KwcContractLogisticsGoods>> logisticsGoodsMap = contractLogisticsGoods.stream().collect(Collectors.groupingBy(KwcContractLogisticsGoods::getContractId));
                for (Long contractId : needCheckGoodsContractIds) {
                    List<KwcContractLogisticsGoods> logisticsGoodList = logisticsGoodsMap.get(contractId);
                    // 提取当前合同下的所有商品ID
                    Set<Long> currentGoodsIds = logisticsGoodList.stream().map(KwcContractLogisticsGoods::getGoodsId).filter(Objects::nonNull).collect(Collectors.toSet());
                    // 校验目标商品ID是否包含
                    boolean isContains = currentGoodsIds.contains(goodsId);
                    if (isContains) {
                        validContractIds.add(contractId);
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(validContractIds)) {
            return Collections.emptyList();
        }
        //过滤满足商品数据
        List<KwcContractLogistics> finalContractList = contractLogisticsList.stream()
                .filter(contract -> validContractIds.contains(contract.getId()))
                .collect(Collectors.toList());

        //过滤有效期合同
        List<KwcContractLogistics> filteredLogistics = finalContractList.stream().filter(Objects::nonNull)
                .filter(con -> con.getStartTime() != null)
                .filter(con -> {
                    return !con.getStartTime().after(new Date());
                }).collect(Collectors.toList());

        return toLogisticsEntDtoVO(entId, filteredLogistics);
    }


    /**
     * 根据合同id和商品id查询物流合同商品信息
     *
     * @param contractId 物流合同
     * @param goodsId    商品id
     * @return
     */
    public LogisticsGoodsDto queryLogGoodsByContractId(Long contractId, Long goodsId) {
        if (Objects.isNull(contractId)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "物流合同id不能为空！");
        }
        if (goodsId == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "商品id不能为空！");
        }
        //查询物流商品合同信息
        KwcContractLogisticsGoods goods = kwcContractLogisticsGoodsRepository.queryByContractIdAndGoodId(contractId, goodsId);
        if (goods == null) {
            return new LogisticsGoodsDto();
        }
        LogisticsGoodsDto dto = new LogisticsGoodsDto();
        dto.setGoodsId(goods.getGoodsId());
        dto.setAmount(goods.getAmount());
        dto.setPrice(goods.getPrice());
        return dto;
    }


    //查询物流合同物流企业信息
    public TradeContractUnitDto queryEntByContractId(Long contractId) {
        KwcContractLogisticsUnit unit = kwcContractLogisticsUnitRepository.queryByLogContractIdUnit(contractId);
        if (unit == null) {
            return new TradeContractUnitDto();
        }
        TradeContractUnitDto tradeContractUnitDto = new TradeContractUnitDto();
        tradeContractUnitDto.setUnitType(String.valueOf(unit.getUnitType()));
        tradeContractUnitDto.setEntId(unit.getEntId());
        tradeContractUnitDto.setFirmName(unit.getFirmName());
        tradeContractUnitDto.setContactsId(unit.getContactsId());
        tradeContractUnitDto.setContacts(unit.getContacts());
        tradeContractUnitDto.setPhone(unit.getPhone());
        return tradeContractUnitDto;

    }

    //查询物流企业评分数据
    public KwcContractLogisticsScore queryEntScoreByEntId(Long proEntId, Long logEntId) {
        KwcContractLogisticsScore logisticsScore = contractLogisticsScoreRepository.findLogisticsScoreByEntId(proEntId, logEntId);
        if (logisticsScore == null) {
            return new KwcContractLogisticsScore();
        }
        return logisticsScore;
    }

    public Long querySign(Long entId, Integer type) {
        return kwcContractTradeMapper.selectSignCount(entId, type);
    }

    /**
     * 获取当前用户的数据权限配置
     *
     * @return 数据权限DTO，如果获取失败则返回null
     */
    private DataPermissionDTO fetchDataPermissionForCurrentUser() {
        try {
            DataPermissionFilterReqDto reqDto = new DataPermissionFilterReqDto();
            reqDto.setUserId(LoginUserHolder.getUserId());
            reqDto.setRoleId(LoginUserHolder.getCurrentRoleId());
            reqDto.setManager(LoginUserHolder.isManager());
            return dataPermissionFeignService.getDataPermissionFilter(reqDto);
        } catch (Exception e) {
            log.warn("获取贸易合同数据权限失败，跳过权限过滤: {}", e.getMessage());
            return null;
        }
    }


    /**
     * 数据权限过滤（{@link #queryTradeListByPage}、{@link #countQueryTradeListByPage}、{@link #queryTradeContractStatusCount} 共用）。
     * <p>
     * 与 {@link DataPermissionDTO} 一致：开启个人数据权限时，条件为「角色已勾选企业范围」与「本人为合同销售员」同时满足（AND）。
     * 企业范围：按 {@code kwc_contract_trade_unit} 中采购/销售等企业的 {@code ent_id} 是否与 {@code visibleEntIds} 有交集；
     * 个人范围：{@code salesman_id} 等于当前用户。未配置企业限制（全部可见）且未开个人权限时不收缩。
     * </p>
     *
     * @param records 待过滤的贸易合同列表
     * @param perm    当前用户的数据权限配置对象
     * @return 过滤后的贸易合同列表
     */
    private List<KwcContractTrade> filterTradeContractsByPermission(List<KwcContractTrade> records, DataPermissionDTO perm) {
        // 如果记录为空、权限配置为空或不需要过滤，直接返回原列表
        if (CollectionUtils.isEmpty(records) || perm == null || !perm.needFilter()) {
            return records;
        }

        log.debug("开始执行贸易合同数据权限过滤，原始记录数: {}, 用户ID: {}", records.size(), perm.getUserId());

        // 提取所有合同ID
        Set<Long> contractIds = records.stream()
                .map(KwcContractTrade::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 构建合同ID与关联企业ID集合的映射关系
        Map<Long, Set<Long>> contractIdEntIdsMap = Collections.emptyMap();
        if (CollectionUtils.isNotEmpty(contractIds)) {
            List<KwcContractTradeUnit> tradeUnits = kwcContractTradeUnitRepository.queryByContractIds(contractIds);
            if (CollectionUtils.isNotEmpty(tradeUnits)) {
                contractIdEntIdsMap = tradeUnits.stream()
                        .filter(unit -> unit.getContractId() != null && unit.getEntId() != null)
                        .collect(Collectors.groupingBy(KwcContractTradeUnit::getContractId,
                                Collectors.mapping(KwcContractTradeUnit::getEntId, Collectors.toSet())));
            }
        }

        Map<Long, Set<Long>> finalContractIdEntIdsMap = contractIdEntIdsMap;

        // 执行过滤逻辑
        List<KwcContractTrade> filteredRecords = records.stream().filter(record -> {
            // 1. 校验企业权限
            boolean entOk = true;
            if (!perm.isAllVisible()) {
                // 如果不是所有企业可见，则检查可见企业ID列表
                if (CollectionUtils.isEmpty(perm.getVisibleEntIds())) {
                    entOk = false;
                    log.debug("合同ID: {} 过滤原因: 非全可见且无可见企业权限", record.getId());
                } else {
                    // 检查当前合同关联的企业中，是否有任意一个在用户的可见企业列表中
                    Set<Long> relationEntIds = finalContractIdEntIdsMap.get(record.getId());
                    entOk = CollectionUtils.isNotEmpty(relationEntIds)
                            && relationEntIds.stream().anyMatch(perm.getVisibleEntIds()::contains);
                    if (!entOk) {
                        log.debug("合同ID: {} 过滤原因: 关联企业不在可见列表中", record.getId());
                    }
                }
            }

            // 2. 校验销售人员个人数据权限
            boolean salesOk = true;
            if (perm.isPersonalDataEnabled()) {
                // 如果开启了个人数据权限，检查当前用户是否为该合同的销售人员
                salesOk = perm.getUserId() != null && Objects.equals(perm.getUserId(), record.getSalesmanId());
                if (!salesOk) {
                    log.debug("合同ID: {} 过滤原因: 非本人销售数据 (当前用户: {}, 销售员: {})",
                            record.getId(), perm.getUserId(), record.getSalesmanId());
                }
            }

            // 同时满足企业权限和销售人员权限才保留
            return entOk && salesOk;
        }).collect(Collectors.toList());

        log.debug("贸易合同数据权限过滤完成，过滤后记录数: {}", filteredRecords.size());
        return filteredRecords;
    }
}

