package com.jwipc.contract.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.aggregation.ModelAggregationService;
import com.jwipc.api.constant.OaStatus;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.api.dto.OaFileParamDTO;
import com.jwipc.api.dto.SubjectDTO;
import com.jwipc.constant.DelFlag;
import com.jwipc.constant.DictCode;
import com.jwipc.constant.SignProcessType;
import com.jwipc.contract.base.ContractDetailClientDTO;
import com.jwipc.contract.client.ContractDetailClient;
import com.jwipc.contract.constant.ContractConst;
import com.jwipc.contract.constant.ContractOaClient;
import com.jwipc.contract.constant.ContractSignClient;
import com.jwipc.contract.convert.ContractConvert;
import com.jwipc.contract.dto.*;
import com.jwipc.contract.entity.*;
import com.jwipc.contract.logic.ContractDeliveryLogic;
import com.jwipc.contract.logic.ContractLogic;
import com.jwipc.contract.logic.ContractSubSeqLogic;
import com.jwipc.contract.model.po.*;
import com.jwipc.contract.model.query.*;
import com.jwipc.contract.service.*;
import com.jwipc.api.esign.HTTPHelper;
import com.jwipc.api.esign.SignUtils;
import com.jwipc.exception.DaoException;
import com.jwipc.inquiry.client.InquiryClient;
import com.jwipc.inquiry.client.PurchaseApplyBillClient;
import com.jwipc.inquiry.dto.PurchaseApplyBillClientDTO;
import com.jwipc.log.constant.ThirdSysType;
import com.jwipc.log.factory.ApiLogTaskFactory;
import com.jwipc.log.logic.LogManager;
import com.jwipc.inquiry.client.PurchaseApplyBillDetailClient;
import com.jwipc.inquiry.dto.PurchaseApplyBillDetailClientDTO;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.query.BasePageQuery;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.clent.dto.CustomerInfoClientDTO;
import com.jwipc.supplier.clent.dto.SupplierBankDTO;
import com.jwipc.supplier.clent.dto.SupplierContactsDTO;
import com.jwipc.supplier.client.SupplierClient;
import com.jwipc.supplier.client.TenderClient;
import com.jwipc.sys.client.*;
import com.jwipc.sys.client.dto.*;
import com.jwipc.sys.constant.FinancialShareClient;
import com.jwipc.sys.dto.CreateFinancialShareContractDTO;
import com.jwipc.sys.dto.FinancialShareApiResultDTO;
import com.jwipc.sys.entity.FinancialShareContract;
import com.jwipc.sys.entity.TaxInfo;
import com.jwipc.sys.service.ITaxService;
import com.jwipc.sys.util.FinancialShareUtil;
import com.jwipc.util.EasyExcelImportUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.jwipc.constant.DictCode.CONTRACT_MRO_SUBJECT;
import static com.jwipc.constant.DictCode.DELIVERY_TYPE;

/**
 * 功能描述:
 *
 * @Author: zx
 * @Date: 2024/3/7 0007 16:28
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ContractLogicImpl implements ContractLogic {


    @Autowired
    IContractService contractService;

    @Autowired
    ContractConvert contractConvert;

    @Autowired
    ContractClient contractClient;

    @Autowired
    SupplierClient supplierClient;

    @Autowired
    DictClient dictClient;

    @Autowired
    IContractPayStageService contractPayStageService;

    @Autowired
    IContractPayService contractPayService;

    @Autowired
    IContractPayDetailService contractPayDetailService;

    @Autowired
    IContractDetailService contractDetailService;

    @Autowired
    IContractDetailMroService mroService;

    @Autowired
    IContractCategoryService contractCategoryService;

    @Autowired
    FileClient fileClient;

    @Resource
    ContractOaClient contractOaClient;

    @Autowired
    IContractPayOrderService payOrderService;

    @Autowired
    IContractPayTypeService payTypeService;

    @Autowired
    TenderClient tenderClient;

    @Autowired
    InquiryClient inquiryClient;

    @Autowired
    ModelAggregationService modelAggregationService;

    @Autowired
    ContractSignClient signClient;

    @Autowired
    PurchaseGroupClient purchaseGroupClient;

    @Autowired
    PurchaseOrgClient purchaseOrgClient;

    @Autowired
    ProductGroupClient productGroupClient;

    @Autowired
    TaxClient taxClient;

    @Autowired
    FactoryClient factoryClient;

    @Autowired
    private final UserClient userClient;

    @Autowired
    private final FinancialShareClient financialShareClient;
    @Autowired
    private final FinancialShareUtil financialShareUtil;
    @Autowired
    private final ITaxService taxService;
    @Autowired
    private final ContractDeliveryLogic contractDeliveryLogic;

    private final IContractDeliveryDetailService contractDeliveryDetailService;

    private final IContractReturnOrderDetailService contractReturnOrderDetailService;
    private final IContractPaymentApplyDetailService contractPaymentApplyDetailService;

    private final PurchaseApplyBillDetailClient purchaseApplyBillDetailClient;

    private final PurchaseApplyBillClient purchaseApplyBillClient;
    private final IContractPaymentApplyService contractPaymentApplyService;
    private final ContractSubSeqLogic contractSubSeqLogic;
    

    @Value("${sys.esign.projectid}")
    private String projectid;

    @Value("${sys.esign.serverip}")
    private String serverip;

    @Value("${sys.esign.projectsecret}")
    private String projectsecret;

    @Value("${sys.esign.businessTypeCode}")
    private String businessTypeCode;

    @Value("${sys.esign.callbackUrl}")
    private String callbackUrl;


    @Autowired
    private ContractDetailClient contractDetailClient;


    @Override
    public PageView listPage(ContractMangeQuery query) {
        final Page<Contract> page = PageUtil.toPage(query);
        LambdaQueryWrapper<Contract> queryWrapper = null;
        if(query.getSupplierFlag()){
            queryWrapper = new LambdaQueryWrapper<Contract>()
                    .eq(Contract::getDeleteFlag,DelFlag.NORMAL.getStatus())
                    .eq(!ObjectUtils.isEmpty(query.getState()),Contract::getContractState, query.getState())
                    .like(!StringUtils.isEmpty(query.getTitle()),Contract::getContractTitle, query.getTitle())
                    .like(!StringUtils.isEmpty(query.getCode()),Contract::getContractCode, query.getCode())
                    .like(!StringUtils.isEmpty(query.getSupplierCode()),Contract::getContractSupplierCode, query.getSupplierCode())
                    .notIn(Contract::getContractState, 0,1)
                    .eq(query.getIsMro()!=null,Contract::getIsMro, query.getIsMro())
                    .eq(!StringUtils.isEmpty(query.getContractDraft()),Contract::getContractDraft, query.getContractDraft())
                    .eq(!StringUtils.isEmpty(query.getType()),Contract::getContractType, query.getType());
        }else{
            queryWrapper = new LambdaQueryWrapper<Contract>()
                    .eq(Contract::getDeleteFlag,DelFlag.NORMAL.getStatus())
                    .eq(!ObjectUtils.isEmpty(query.getState()),Contract::getContractState, query.getState())
                    .like(!StringUtils.isEmpty(query.getTitle()),Contract::getContractTitle, query.getTitle())
                    .like(!StringUtils.isEmpty(query.getContractSupplierName()),Contract::getContractSupplierName, query.getContractSupplierName())
                    .like(!StringUtils.isEmpty(query.getCode()),Contract::getContractCode, query.getCode())
                    .eq(!StringUtils.isEmpty(query.getContractDemandUser()),Contract::getContractDemandUser, query.getContractDemandUser())
                    .in(CollUtil.isNotEmpty(query.getList()),Contract::getContractPurchaseGroup,query.getList())
                    .eq(query.getIsMro()!=null,Contract::getIsMro, query.getIsMro())
                    .eq(!StringUtils.isEmpty(query.getContractDraft()),Contract::getContractDraft, query.getContractDraft())
                    .eq(!StringUtils.isEmpty(query.getType()),Contract::getContractType, query.getType());
        }

        applySort(queryWrapper, query);
        List<Contract> contracts = contractService.list(page,queryWrapper );
        List<ContractDTO> contractDTOS = contractConvert.entitiesPoToDto(contracts);
        return PageUtil.getPV(contractDTOS, page.getTotal());
    }

    @Override
    public PageView reportPage(ContractMangeQuery query) {
        final Page<Contract> dbPage = PageUtil.toPage(query);
        List<ContractReportPO> contractReportPOS = contractService.reportPage(dbPage, query);
        List<ContractReportDTO> contractReportDTOS = contractConvert.reportPO2DTOList(contractReportPOS);
        contractReportDTOS.forEach(contractReportDTO -> {
            if (contractReportDTO.getPrice() != null&& contractReportDTO.getNum() != null){
                contractReportDTO.setContractDetailAmount(contractReportDTO.getPrice().multiply(contractReportDTO.getNum()));
//                if (contractReportDTO.getTotalAmount()!=null){
//                    //降价率（合同行金额-采购申请行总金额）/合同行金额
//                    BigDecimal chajia = contractReportDTO.getContractDetailAmount().subtract(contractReportDTO.getTotalAmount());
//                    contractReportDTO.setIncreasePrice(chajia.divide(contractReportDTO.getContractDetailAmount(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString());
//                }

            }
        });
        return PageUtil.getPV(contractReportDTOS, dbPage.getTotal());
    }

    @Override
    public List<ContractReportDTO> listAll(ContractMangeQuery query) {
        List<ContractReportPO> contractReportPOS = contractService.reportPage(null, query);
        List<ContractReportDTO> contractReportDTOS = contractConvert.reportPO2DTOList(contractReportPOS);
        contractReportDTOS.forEach(contractReportDTO -> {
            if (contractReportDTO.getPrice() != null&& contractReportDTO.getNum() != null){
                contractReportDTO.setContractDetailAmount(contractReportDTO.getPrice().multiply(contractReportDTO.getNum()));
            }
        });
        return contractReportDTOS;
    }

    @Override
    public PageView choseContractList(ContractMangeQuery query) {
        final Page<Contract> page = PageUtil.toPage(query);
        LambdaQueryWrapper queryWrapper = queryWrapper = new LambdaQueryWrapper<Contract>()
                .eq(Contract::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .in(Contract::getContractState, 3,5)
                .like(!StringUtils.isEmpty(query.getTitle()),Contract::getContractTitle, query.getTitle())
                .eq(!StringUtils.isEmpty(query.getCode()),Contract::getContractCode, query.getCode())
                .orderByDesc(Contract::getCreateTime);
        List<Contract> contracts = contractService.list(page,queryWrapper );
        List<ContractDTO> contractDTOS = contractConvert.entitiesPoToDto(contracts);
        return PageUtil.getPV(contractDTOS, page.getTotal());
    }

    @Override
    public ContractDTO formDeatil(String id) {
        Contract bean = contractService.getById(id);
        return contractConvert.entitiePoToDto(bean) ;
    }

    @Override
    public ContractPayDTO formPayDeatil(String id) {
        ContractPay contractPay = contractPayService.getById(id);
        return contractConvert.entitiePoToDto(contractPay) ;
    }

    @Override
    public PageView choseSupplierList(ChoseSupplierListQuery choseSupplierListQuery) {
        PageView pageView = new PageView();
        if (choseSupplierListQuery.getType().equals("1")) {
            pageView = contractClient.getSupplierList(JSON.toJSONString(choseSupplierListQuery));
        }else{
            pageView = supplierClient.getSupplierList(JSON.toJSONString(choseSupplierListQuery));
        }
        return pageView;
    }

    @Override
    public Long selectOnlyCode(String code, Long conId) {
        Long count = contractService.count(
                new LambdaQueryWrapper<Contract>()
                        .eq(Objects.nonNull(code),Contract::getContractCode, code)
                        .notIn(Objects.nonNull(conId),Contract::getId, conId));
        return count;
    }

    @Override
    public void insertOrUpdate(Contract bean) {
        if (("07".equals(bean.getContractType()) || "08".equals(bean.getContractType()))
                && StringUtils.isEmpty(bean.getContractCode())) {
            bean.setContractCode(contractSubSeqLogic.getRealSubContractCode(bean.getAssociationContract()));
        }
        contractService.saveOrUpdate(bean);
    }

    @Override
    public void saveContractDeatils(Contract bean, String dlist,String rowsTableTblist,String mros) {
        //del
        contractPayStageService.update(new LambdaUpdateWrapper<ContractPayStage>()
                .set(ContractPayStage::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPayStage::getContractId,bean.getId())
        );
        contractDetailService.update(new LambdaUpdateWrapper<ContractDetail>()
                .set(ContractDetail::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractDetail::getContractId,bean.getId())
        );
        mroService.update(new LambdaUpdateWrapper<ContractDetailMro>()
                .set(ContractDetailMro::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractDetailMro::getContractId,bean.getId())
        );
        List<ContractPayStage> stages = JSON.parseArray(dlist,ContractPayStage.class);
        List<ContractDetail> details = JSON.parseArray(rowsTableTblist,ContractDetail.class);
        List<ContractDetailMro> mrosList = JSON.parseArray(mros,ContractDetailMro.class);
        //save dlist
        AtomicInteger stageCounter = new AtomicInteger(1);
        if(stages!=null&&stages.size()>0){
            stages.stream().forEach(a-> {
                a.setContractCode(bean.getContractCode());
                a.setContractId(bean.getId());
                a.setDeleteFlag(0);
                a.setLineNo(stageCounter.getAndIncrement());
            });
            contractPayStageService.saveOrUpdateBatch(stages);
        }
        AtomicInteger lineNoCounter = new AtomicInteger(1);
        if(details!=null&&details.size()>0){
            details.stream().forEach(a-> {
                a.setContractCode(bean.getContractCode());
                a.setContractId(bean.getId());
                a.setDeleteFlag(0);
                a.setLineNo(lineNoCounter.getAndIncrement());
            });
            contractDetailService.saveOrUpdateBatch(details);
        }
        if(mrosList!=null&&mrosList.size()>0){
            mrosList.stream().forEach(a-> {
                a.setContractCode(bean.getContractCode());
                a.setContractId(bean.getId());
                a.setDeleteFlag(0);
            });
            mroService.saveOrUpdateBatch(mrosList);
        }
        //回写状态
        if(bean.getDataSources().equals(ContractConst.DATASOURCES_ZB)){
            tenderClient.updateConState(bean.getDataSourcesId(), 1);
        }
        if(bean.getDataSources().equals(ContractConst.DATASOURCES_XJ)){
            inquiryClient.updateConState(bean.getDataSourcesId(),1);
        }
        if(bean.getDataSources().equals(ContractConst.DATASOURCES_BATCH_XJ)){
            inquiryClient.updateConStateByNos(bean.getDataSourcesNo(),bean.getContractSupplierCode(),1);
        }

        if (StrUtil.isNotEmpty(bean.getDataSourcesNo())&&bean.getDataSourcesNo().contains("RFQ")){
            inquiryClient.updateConStateByNos(bean.getDataSourcesNo(),bean.getContractSupplierCode(),1);
        }

    }

    @Override
    public void removeContract(String id) {
        contractService.update(new LambdaUpdateWrapper<Contract>().set(Contract::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(Contract::getId,id)
        );

        contractDetailService.update(new LambdaUpdateWrapper<ContractDetail>().set(ContractDetail::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractDetail::getContractId,id)
        );
        //如果合同被废弃，则须把之前的转合同数量置为初始状态 2024-10-29 邓京术
        //根据合同是 0 自建 ， 1 招标  ， 2 询价  3 批量询价生成的合同
        //为了不影响之前的操作，Try catch 包起来
        Contract contract = contractService.getOne(
                new LambdaQueryWrapper<Contract>().eq(Contract::getId, id));
        try {
            switch (contract.getDataSources()) {
                case 0:
                    if (contract.getDataSourcesId() != null && org.apache.commons.lang3.StringUtils.isNotEmpty(contract.getDataSourcesNo())) {
                        if (contract.getDataSourcesNo().contains("RFQ")) {
                            inquiryClient.updateConStateByNos(contract.getDataSourcesNo(), contract.getContractSupplierCode(),0);
                        } else {
                            tenderClient.updateConState(contract.getDataSourcesId(), 0);
                        }
                    }
                    break;
                case 1:
                    tenderClient.updateConState(contract.getDataSourcesId(), 0);
                    break;
                case 2:
                    inquiryClient.updateConState(contract.getDataSourcesId(), 0);
                    break;
                case 3:
                    inquiryClient.updateConStateByNos(contract.getDataSourcesNo(), contract.getContractSupplierCode(),0);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void saveSignFile(MultipartFile[] files , String[] fileIds, String conId) {
        StringBuilder fileKeysBuilder = new StringBuilder();
        StringBuilder fileIdssBuilder = new StringBuilder();

        for(int i = 0; i < files.length; i++) {
            String fileKey = uploadSignFile(files[i],fileIds[i]);
            if(i > 0) {
                fileKeysBuilder.append(",");
                fileIdssBuilder.append(",");
            }
            fileKeysBuilder.append(fileKey);
            fileIdssBuilder.append(fileIds[i]);
        }
        contractService.update(new LambdaUpdateWrapper<Contract>().set(Contract::getContractSignFiels,fileIdssBuilder.toString())
                .set(Contract::getContractSignFileStatue, ContractConst.MANUAL)
                .set(Contract::getFileKey,fileKeysBuilder.toString())
                .eq(Contract::getId,conId));
    }


    @Override
    public String uploadSignFile(MultipartFile file, String fileId) {
        //文件直传
        FileResposeCDTO fileResposeDTO = fileClient.getFileInfo(Long.valueOf(fileId));

        String getInnerOrganizationsDetailApi = "/file/v1/upload";
        String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;

        JSONObject reqBodyObj = new JSONObject();
        reqBodyObj.put("file", fileResposeDTO.getFileName());
        reqBodyObj.put("hash", SignUtils.sign256("",fileResposeDTO.getHash()));
        // 请求Body体数据
        String reqBodyData = reqBodyObj.toString();
        log.info("上传盖章附件接口参数：{}",reqBodyData);
        // 构建参与请求签名计算的明文
        String plaintext = reqBodyData;
        // 计算请求签名值
        String reqSignature = SignUtils.sign256(plaintext, projectsecret);

        LinkedHashMap<String, String> header = new LinkedHashMap<>();
        // 构建待签名字符串
        String accept = "*/*";
        header.put("X-timevale-project-id", projectid);
        header.put("X-timevale-signature", reqSignature);
        header.put("Accept", accept);
        String fileFieldName = "file";

        // 发送POST请求
        String result = null;
        try {
            result = HTTPHelper.uploadFile1(uploadApiUrl, fileFieldName, file, reqBodyObj,  header, "UTF-8");
            log.info("上传盖章附件接口返回结果：{}",reqBodyData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            //调用方日志
            LogManager.me().executeLog(ApiLogTaskFactory.saveCallLog("uploadFile", "上传盖章文件接口",
                    ThirdSysType.SIGN.getType(),
                    reqBodyData,
                    result,
                    "",
                    LocalDateTime.now()
            ));
        }
        System.out.println(JSON.toJSONString("result----"+result));
        ApiResult json = JSON.parseObject(result,ApiResult.class);
        if(json.getCode().equals(RestCode.MES_SUCCESS.getCode())){
            JSONObject dataJson = (JSONObject)json.getData();
            return dataJson.getString("fileKey");
        }else {
            throw new DaoException(json.getMessage());
        }
    }

    @Override
    public PageView selectPayListPage(ChoseSupplierListQuery query) {
        final Page<ContractPayStage> page = PageUtil.toPage(query);
        List<ContractPayStage> payStages = contractPayStageService.list(page,
                new LambdaQueryWrapper<ContractPayStage>()
                        .eq(ContractPayStage::getDeleteFlag,DelFlag.NORMAL.getStatus())
                        .eq(ContractPayStage::getContractId, query.getConId())
        );
        return PageUtil.getPV(payStages, page.getTotal());
    }

    @Override
    public PageView contractPayListPage(ContractMangeQuery query) {

        final Page<ContractPay> page = PageUtil.toPage(query);
        List<ContractPay> pays = contractPayService.findListPage(page, query);
//        List<ContractPay> pays = contractPayService.list(page,
//                new LambdaQueryWrapper<ContractPay>()
//                        .eq(ContractPay::getDeleteFlag,DelFlag.NORMAL.getStatus())
//                        .like(!StringUtils.isEmpty(query.getTitle()),ContractPay::getPayTitle, query.getTitle()).orderByDesc(ContractPay::getId));
        return PageUtil.getPV(pays, page.getTotal());

    }

    @Override
    public PageView choseContractHistoryList(ChoseSupplierListQuery query) {
        final Page<Contract> page = PageUtil.toPage(query);
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<Contract>()
                .eq(Contract::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .like(!StringUtils.isEmpty(query.getNameCOde()),Contract::getContractTitle, query.getNameCOde())
                .like(!StringUtils.isEmpty(query.getSupplierName()),Contract::getContractSupplierName, query.getSupplierName())
                .eq(Contract::getContractState, 3)
                .gt(Contract::getContractAmount, 0)
                .orderByDesc(Contract::getCreateTime);
        List<Contract> contracts = contractService.list(page,queryWrapper );
        List<ContractDTO> contractDTO = contractConvert.entitiesPoToDto(contracts) ;
        contractDTO.stream().forEach(a->{
            List<ContractPayStage> contractPayStageList = contractPayStageService.getContractPayStageList(a.getId());
            BigDecimal sumPaymentPlusAmount = BigDecimal.ZERO;
            for (ContractPayStage contractPayStage : contractPayStageList) {
                sumPaymentPlusAmount = sumPaymentPlusAmount.add(contractPayStage.getPaymentPlusAmount());
            }

            a.setPayStages(contractPayStageService.getContractPayStageList(a.getId()));
            a.setSumPaymentPlusAmount(sumPaymentPlusAmount);
            //a.setPayStages(contractPayStageService.list(new LambdaQueryWrapper<ContractPayStage>().eq(ContractPayStage::getContractId,a.getId())));
        });
        return PageUtil.getPV(contractDTO, page.getTotal());
    }

    @Override
    public List<SupplierBankDTO> supplierBankDate(String contractSupplierCode) {
        return supplierClient.supplierBankDate(contractSupplierCode);
    }

    @Override
    public String  getTotalPayAmount(String contractCode){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        BigDecimal totalPayAmount =new BigDecimal(0.00);
        List<ContractPay> payList = contractPayService.list(new LambdaQueryWrapper<ContractPay>().eq(ContractPay::getDeleteFlag,0).eq(ContractPay::getContractCode,contractCode).in(ContractPay::getPayState ,list));
        if(!CollectionUtils.isEmpty(payList)){
            for(ContractPay pay :payList){
                totalPayAmount = totalPayAmount.add(pay.getTotalAmount()==null?BigDecimal.ZERO:pay.getTotalAmount());
            }
        }
        return totalPayAmount.toString();
    }

    @Override
    public PageView detailLists(ContractPayDetailsQuery payDetailsQuery) {
        final Page<ContractPayDetailsVo> page = PageUtil.toPage(payDetailsQuery);
        List<ContractPayDetailsVo> contractPayDetailsVos = contractPayDetailService.detailLists(page,payDetailsQuery );
        if(!CollectionUtils.isEmpty(contractPayDetailsVos)){
            contractPayDetailsVos.stream().forEach(a->{
                String amountPaid=contractPayDetailService.getAmountPaid(a.getContractId(),a.getPayStageId());
                a.setAmount(a.getPaymentAmount().subtract(new BigDecimal(amountPaid==null?"0.00":amountPaid)));
                a.setAmountPaid(new BigDecimal(amountPaid==null?"0.00":amountPaid));
            });

            /*//查询对应的累计金额
            List<String> payStageIds = contractPayDetailsVos.stream().map(a->String.valueOf(a.getPayStageId())).distinct().collect(Collectors.toList());
            List<String> contractIds = contractPayDetailsVos.stream().map(a->String.valueOf(a.getContractId())).distinct().collect(Collectors.toList());
            Map<Long, BigDecimal> map = amountSum(String.join(",",payStageIds),String.join(",",contractIds),payDetailsQuery.getPayId());
            if(!StringUtils.isEmpty(map)){
                contractPayDetailsVos.stream().forEach(a->{
                    BigDecimal amount = map.containsKey(a.getPayStageId())?map.get(a.getPayStageId()):BigDecimal.ZERO;
                    a.setAmountPaid(amount);
                });
            }*/
        }
        return PageUtil.getPV(contractPayDetailsVos, page.getTotal());
    }

    @Override
    public PageView detailOrderLists(ContractPayDetailsQuery payDetailsQuery) {
        final Page<ContractPayOrder> page = PageUtil.toPage(payDetailsQuery);
        LambdaQueryWrapper queryWrapper = queryWrapper = new LambdaQueryWrapper<ContractPayOrder>()
                .eq(ContractPayOrder::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .in(ContractPayOrder::getPayId, payDetailsQuery.getPayId())
                .orderByDesc(ContractPayOrder::getId);
        List<ContractPayOrder> contracts = payOrderService.list(page,queryWrapper );
        List<ContractPayOrderDTO> contractDTOS = contractConvert.contractPayOrderEntitieDtoToPo(contracts);
        return PageUtil.getPV(contractDTOS, page.getTotal());
    }

    @Override
    public PageView detailTypeLists(ContractPayDetailsQuery payDetailsQuery) {
        final Page<ContractPayType> page = PageUtil.toPage(payDetailsQuery);
        LambdaQueryWrapper queryWrapper = queryWrapper = new LambdaQueryWrapper<ContractPayType>()
                .eq(ContractPayType::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .in(ContractPayType::getPayId, payDetailsQuery.getPayId())
                .orderByDesc(ContractPayType::getId);
        List<ContractPayType> contracts = payTypeService.list(page,queryWrapper );
        List<ContractPayTypeDTO> contractDTOS = contractConvert.contractPayTypeEntitieDtoToPo(contracts);
        return PageUtil.getPV(contractDTOS, page.getTotal());
    }

    @Override
    public List<ContractPayTypeDTO> detailTypeListByContractId(Long contractId) {
        List<ContractPayType> contracts = payTypeService.detailTypeListByContractId(contractId);
        contracts.forEach(contractPayType -> {
            if (ObjectUtil.isNotNull(contractPayType.getNum())&&ObjectUtil.isNotNull(contractPayType.getPrice())){
                contractPayType.setAmount(contractPayType.getNum().multiply(contractPayType.getPrice()));
            }
            if (StrUtil.isNotEmpty(contractPayType.getMaterialSpec())){
                contractPayType.setBz(contractPayType.getBz()+contractPayType.getMaterialSpec());
            }
        });
        return contractConvert.contractPayTypeEntitieDtoToPo(contracts);
    }

    @Override
    public Long selectOnlyPayCode(String code, Long payId) {
        Long count = contractPayService.count(
                new LambdaQueryWrapper<ContractPay>()
                        .eq(Objects.nonNull(code),ContractPay::getPayCode, code)
                        .notIn(Objects.nonNull(payId),ContractPay::getId, payId));
        return count;
    }

    @Override
    public void insertOrUpdateByPay(ContractPayDTO bean) {
        ContractPay contractPay = contractConvert.entitieDtoToPo(bean);
        contractPayService.saveOrUpdate(contractPay);
    }

    @Override
    public void saveContractPayDeatils(ContractPayDTO bean, String dlist,String orderlist,String typelist) {
        ContractPay contractPay = contractConvert.entitieDtoToPo(bean);
        contractPayService.saveOrUpdate(contractPay);
        //del
        contractPayDetailService.update(new LambdaUpdateWrapper<ContractPayDetail>()
                .set(ContractPayDetail::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPayDetail::getPayId,bean.getId())
        );
      /*  payOrderService.update(new LambdaUpdateWrapper<ContractPayOrder>()
                .set(ContractPayOrder::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPayOrder::getPayId,bean.getId())
        );*/
        payTypeService.update(new LambdaUpdateWrapper<ContractPayType>()
                .set(ContractPayType::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPayType::getPayId,bean.getId())
        );
        List<ContractPayDetail> stages = JSON.parseArray(dlist,ContractPayDetail.class);
        // List<ContractPayOrder> orders = JSON.parseArray(orderlist,ContractPayOrder.class);
        List<ContractPayType> types = JSON.parseArray(typelist,ContractPayType.class);
        //save dlist
        if(stages!=null&&stages.size()>0){
            stages.stream().forEach(a-> {
                a.setPayId(contractPay.getId());
                a.setId(null);
            });
            contractPayDetailService.saveBatch(stages);
        }
        /*if(orders!=null&&orders.size()>0){
            orders.stream().forEach(a-> {
                a.setPayId(contractPay.getId());
                a.setId(null);
            });
            payOrderService.saveBatch(orders);
        }*/
        if(types!=null&&types.size()>0){
            types.stream().forEach(a-> {
                a.setPayId(contractPay.getId());
                a.setId(null);
            });
            payTypeService.saveBatch(types);
        }
    }

    @Override
    public void removeContractPay(String id) {
        contractPayService.update(new LambdaUpdateWrapper<ContractPay>().set(ContractPay::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPay::getId,id)
        );
        contractPayDetailService.update(new LambdaUpdateWrapper<ContractPayDetail>()
                .set(ContractPayDetail::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractPayDetail::getPayId,id)
        );
    }

    @Override
    public ContractDetailDTO formDetail(String detailId) {
        ContractDetail contractDetail =  contractDetailService.getById(detailId);
        return contractConvert.entitieDtoToPo(contractDetail);
    }


    @Override
    public ContractMroDTO formDetailMro(String detailId) {
        ContractDetailMro mro =  mroService.getById(detailId);
        return contractConvert.entitieMroPoToDto(mro);
    }

    @Override
    public PageView selectMroContractDetailListPage(ChoseSupplierListQuery query) {
        final Page<ContractDetailPO> page = PageUtil.toPage(query);
        List<ContractDetailPO> contractPOS = contractDetailService.findListPage(page,query);
        List<ContractDetailDTO> contractDTOS = contractConvert.detailPOToDTOList(contractPOS);
        //计算已付款金额， 已申请金额
        for (ContractDetailDTO contractDetailDTO : contractDTOS) {
            //查询已付款金额及已申请金额
            List<CreateContractPayDetailPO> alreadyData = contractPaymentApplyDetailService.findByAccountByStageId(contractDetailDTO.getId());
            BigDecimal alreadyApplyAmount = BigDecimal.ZERO;
            BigDecimal alreadyPaymentAmount = BigDecimal.ZERO;
            for (CreateContractPayDetailPO detailDto : alreadyData) {
                alreadyApplyAmount = alreadyApplyAmount.add(detailDto.getBudOutMoney());
                //已付款完成的总金额
                if (detailDto.getStatus() == 5) {
                    alreadyPaymentAmount = alreadyPaymentAmount.add(detailDto.getBudOutMoney());
                }
            }
            //已申请金额
            contractDetailDTO.setApplyAlreadyAmount(alreadyApplyAmount);
            //已付款金额
            contractDetailDTO.setPaymentAlreadyAmount(alreadyPaymentAmount);
            //合同请款： 1、合同请款计算已请款金额、已付款金额，需要考虑期初的合同请款金额，按合同付款阶段统计期初合同阶段请款金额
            Map<Long,Long> payStageIdMap = Maps.newHashMap();
            List<ContractPayStagePO> contractPayStageList = contractPayStageService.findContractPayStageList();
//            if (!CollectionUtils.isEmpty(contractPayStageList)) {
                for (ContractPayStagePO contractPayStagePO : contractPayStageList) {
                    if (!payStageIdMap.containsKey(contractPayStagePO.getId()) && contractPayStagePO.getId() == contractDetailDTO.getId()) {
                        contractDetailDTO.setApplyAlreadyAmount(contractDetailDTO.getApplyAlreadyAmount().add(contractPayStagePO.getPaymentIngAmount() == null ? BigDecimal.ZERO : contractPayStagePO.getPaymentIngAmount()));
                        contractDetailDTO.setApplyAlreadyAmount(contractDetailDTO.getApplyAlreadyAmount().add(contractPayStagePO.getPaymentAlreadyAmount() == null ? BigDecimal.ZERO : contractPayStagePO.getPaymentAlreadyAmount()));


                        contractDetailDTO.setPaymentAlreadyAmount(contractDetailDTO.getApplyAlreadyAmount().add(contractPayStagePO.getPaymentAlreadyAmount() == null?BigDecimal.ZERO : contractPayStagePO.getPaymentAlreadyAmount()));
                        contractDetailDTO.setApplyAlreadyAmount(contractDetailDTO.getApplyAlreadyAmount().add(contractPayStagePO.getPaymentIngAmount() == null ? BigDecimal.ZERO : contractPayStagePO.getPaymentIngAmount()));
                        contractDetailDTO.setApplyAlreadyAmount(contractDetailDTO.getPaymentAlreadyAmount().add(contractPayStagePO.getPaymentIngAmount() == null ? BigDecimal.ZERO : contractPayStagePO.getPaymentIngAmount()));
                        payStageIdMap.put(contractPayStagePO.getId(),contractPayStagePO.getId());
                        break;
                    }
                }
//            }
//            contractDetailDTO.setPaymentAlreadyAmount(BigDecimal.ZERO);
//            contractDetailDTO.setPaymentAlreadyAmount(BigDecimal.ZERO);
        }
        return PageUtil.getPV(contractDTOS, page.getTotal());
    }

    @Override
    public PageView selectContractDetailListPage(ChoseSupplierListQuery query) {
        final Page<ContractDetail> page = PageUtil.toPage(query);
        List<ContractDetail> details = contractDetailService.list(new LambdaQueryWrapper<ContractDetail>()
                .eq(ContractDetail::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .eq(ContractDetail::getContractId, query.getConId()));
        if (CollectionUtil.isNotEmpty(details)){
            List<DictDTO> subs = dictClient.getDicByType("stock_point");
            Map<String, String> subMap = subs.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1,key2)->key2));

            for(ContractDetail contractDetail:details){
                PurchaseApplyBillDetailClientDTO applyBillDetail = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(contractDetail.getPurchaseCode(), contractDetail.getItemCode());
                List<ContractDetailClientDTO> contractDetailClientDTOS = contractDetailClient.getDetailListByPurchaseCodeAndeItem(contractDetail.getPurchaseCode(), contractDetail.getItemCode());
                if (CollectionUtil.isNotEmpty(contractDetailClientDTOS)) {
                    List<ContractDetailClientDTO> collect = contractDetailClientDTOS.stream().filter(contractDetailClientDTO -> !contractDetailClientDTO.getContractId().toString().equals(query.getConId())).collect(Collectors.toList());
                    List<BigDecimal> numSum= collect.stream().map(ContractDetailClientDTO::getNum).collect(Collectors.toList());
                    if(CollectionUtil.isNotEmpty(numSum)){
                        BigDecimal sum = numSum.stream()
                                .filter(Objects::nonNull)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal subtract = contractDetail.getNum()==null?BigDecimal.ZERO:contractDetail.getNum().subtract(sum);
                        contractDetail.setEnablePurchaseNum(subtract==null?BigDecimal.ZERO:subtract);
                    }else{
                        contractDetail.setEnablePurchaseNum(applyBillDetail.getApprovalNumber());
                    }
                }else{
                    contractDetail.setEnablePurchaseNum(applyBillDetail.getApprovalNumber());
                }
                contractDetail.setAmount(contractDetail.getNum().multiply(contractDetail.getPrice()));
                contractDetail.setServiceUser(contractDetail.getCustomerName());
                contractDetail.setDriveBz(contractDetail.getDriverAsset());
                contractDetail.setStockPointName(subMap.get(contractDetail.getStockPoint()));
            }
//            details.forEach(contractDetail -> {
//
//            });
        }

        return PageUtil.getPV(details, page.getTotal());
    }


    @Override
    public PageView selectContractMroListPage(ChoseSupplierListQuery query) {
        final Page<ContractDetailMro> page = PageUtil.toPage(query);
        List<ContractDetailMro> details = mroService.list(new LambdaQueryWrapper<ContractDetailMro>()
                .eq(ContractDetailMro::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .eq(ContractDetailMro::getContractId, query.getConId()));
        List<ContractDetailMroDTO> lists = contractConvert.contractMroEntitieDtoToPo(details);
        modelAggregationService.processRelationAggregation(lists);
        return PageUtil.getPV(lists, page.getTotal());
    }


    @Override
    public ContractPayStageDTO getFromPayDetail(Long payId) {
        ContractPayStage stage = contractPayStageService.getById(payId);
        return contractConvert.contractPayStageEntitiePoToDTO(stage);
    }

    @Override
    public List<ContractCategoryDTO> getContractCategory(Integer mroFlag) {
        List<ContractCategory> lists = contractCategoryService.list(new LambdaQueryWrapper<ContractCategory>()
                .eq(ContractCategory::getMroFlag,mroFlag)
                .eq(ContractCategory::getDeleteFlag,DelFlag.NORMAL.getStatus()));
        return contractConvert.contractCategoryEntitieDtoToPo(lists);
    }

    @Override
    public Map<Long, BigDecimal> amountSum(String payStageIds,String contractIds , String payId) {
        List<AmountSumVO> amountSumVOS = contractPayDetailService.amountSum(payStageIds,contractIds,payId);
        Map<Long, BigDecimal> map = amountSumVOS.stream().collect(Collectors.toMap(AmountSumVO::getPayStageId,AmountSumVO::getAmount));
        return map;
    }

    @Override
    public ApiResult getBillByKm(String conId, String oaApplyId) {

        Contract contract = contractService.getById(conId);
//        ContractPO contract1 = contractService.getByQuery(conId);

        List<DictDTO> contractPayBootItemDTOS = dictClient.getDicByType(DictCode.CONTRACT_PAY_BOOT_ITEM.getCode());
        final Map<String, DictDTO> contractPayBootItemCache = contractPayBootItemDTOS.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));

        List<DictDTO> type = dictClient.getDicByType("sign_type");
        Map<String, String> typeMap = type.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1,key2)->key2));


        List<ContractDetail> details = contractDetailService.list(new LambdaQueryWrapper<ContractDetail>().eq(ContractDetail::getContractId,conId)
                .eq(ContractDetail::getDeleteFlag,DelFlag.NORMAL.getStatus()));

        List<ContractDetailMro> mros = mroService.list(new LambdaQueryWrapper<ContractDetailMro>().eq(ContractDetailMro::getContractId,conId)
                .eq(ContractDetailMro::getDeleteFlag,DelFlag.NORMAL.getStatus()));

        List<DictDTO> subs = dictClient.getDicByType("contractContentLink");
        Map<String, String> subMap = subs.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1,key2)->key2));

        List<DictDTO> poType = dictClient.getDicByType("po_type");
        Map<String, String> poTypeMap = poType.stream().collect(Collectors.toMap(DictDTO::getName,DictDTO::getCode,(key1,key2)->key2));

        ContractOA oa = new ContractOA();
        final ContractOA.Head head = new ContractOA.Head();
        head.RecordId=contract.getId();
        head.ProcessId=oaApplyId;

        head.Applicant=contract.getUserAccount();
        LocalDateTime dateTime = contract.getCreateTime();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDateTime = dateTime.format(formatter);
        head.ApplyDate=formattedDateTime;
        //合同文件
        String files = contract.getContractFiles();
        List<String> previews = new ArrayList<>();
        List<OaFileParamDTO> lists = new ArrayList<>();
        if(!StringUtils.isEmpty(files)){
            List<FileResposePreviewCDTO>  previewDTOS = fileClient.getPreviewUrl(Arrays.asList(files.split(",")));
            previewDTOS.stream().forEach(a->{
                final OaFileParamDTO build = OaFileParamDTO.builder().url(a.getPreviewUrl())
                        .fileName(a.getFileName()).downloadUrl(a.getDownloadUrl()).build();
                lists.add(build);
            });

        }
        //contract_files// 合同文件
        //contract_sign_fiels || sign_file 取其一传给OA作为盖章后文件
        String signFiles = contract.getContractSignFiels();
        List<OaFileParamDTO> signLists = new ArrayList<>();
        if(!StringUtils.isEmpty(signFiles)){
            List<FileResposePreviewCDTO>  previewDTOS = fileClient.getPreviewUrl(Arrays.asList(signFiles.split(",")));
            previewDTOS.stream().forEach(a->{
                final OaFileParamDTO build = OaFileParamDTO.builder().url(a.getPreviewUrl())
                        .fileName(a.getFileName()).downloadUrl(a.getDownloadUrl()).build();
                signLists.add(build);
            });

        }
        //mro合同特有
        String signFile = contract.getSignFile();
        List<OaFileParamDTO> signFileLists = new ArrayList<>();
        if(!StringUtils.isEmpty(signFile)){
            List<FileResposePreviewCDTO>  previewDTOS = fileClient.getPreviewUrl(Arrays.asList(signFiles.split(",")));
            previewDTOS.stream().forEach(a->{
                final OaFileParamDTO build = OaFileParamDTO.builder().url(a.getPreviewUrl())
                        .fileName(a.getFileName()).downloadUrl(a.getDownloadUrl()).build();
                signFileLists.add(build);
            });

        }
        if(contract.getIsMro().equals(1)){
            List<ContractOA.Item> items = new ArrayList<>();
            head.SRMToS = ContractConst.BUSINESS_TYPE;

            head.SealType = typeMap.get(contract.getContractSealType());
            head.PurchaseOrgCode=contract.getContractPurchaseGroupCode();
            PurchaseOrgDTO orgDTO = purchaseOrgClient.getByCode(contract.getContractPurchaseGroupCode());
            head.PurchaseOrgName=orgDTO.getPurchaseOrgDesc();
//            head.PurchaseOrgName=contract1.getPurchaseOrgDesc();
            head.OrgCode=contract.getContractPurchaseGroupCode();
            head.PurchaseGroupCode=contract.getContractPurchaseGroup();
            PurchaseGroupDTO groupDTO = purchaseGroupClient.getByCode(contract.getContractPurchaseGroup());
            head.PurchaseGroupName=groupDTO.getPurchaseGroupName();
//            head.PurchaseOrgName=contract1.getPurchaseGroupName();
            // OA合同订单类型
            String[] orderTypeArray = {"Z001", "Z002", "Z003","Z004","Z005","Z006","Z007","Z008","Z009"};
            List<String> list = Arrays.asList(orderTypeArray);
            if(list.contains(contract.getContractOrderType())){
                head.OrderType = contract.getContractOrderType();
            }else{
                String orderTypeValue = poTypeMap.get(contract.getContractOrderType());
                head.OrderType=orderTypeValue;
            }

            head.CompanyCode=contract.getContractCompanyCode();
            head.CompanyName=contract.getContractCompanyName();
            head.ContractYypeCode=contract.getContractType();
            head.ContractTypeName2=contract.getContractType();
            head.ContractTypeCode="";
            head.ContractTypeName="";
            head.SupplierFullName=contract.getContractSupplierName();
            head.SupplierCode=contract.getContractSupplierCode();
            head.Currency=contract.getContractCurrency();
            head.ContractNumber=contract.getContractCode();
            head.Attachments=JSON.toJSONString(lists);
            //合同文件
            head.StampFile=JSON.toJSONString(lists);
            //盖章文件
            // head.StampFile=JSON.toJSONString(signLists);
            if(!CollectionUtils.isEmpty(signFileLists)){
                head.StampedAttachment=JSON.toJSONString(signFileLists);
            }
            if(!CollectionUtils.isEmpty(signLists)){
                head.StampedAttachment=JSON.toJSONString(signLists);
            }

            head.TransferSap=contract.getIsSap();

            if(!CollectionUtils.isEmpty(details)){
                List<Map> mapList = new ArrayList<>();
                details.stream().forEach(d->{
                    Map map = new HashMap();
                    ContractOA.Item item = new ContractOA.Item();
                    PurchaseApplyBillDetailClientDTO applyBillDetail = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(d.getPurchaseCode(),d.getItemCode());
                    map.put("subject",d.getPurchaseName());
                    map.put("docId",d.getPurchaseCode());
                    mapList.add(map);
                    item.Course=d.getSubjectCode();
                    item.MaterialNumber=StrUtil.isEmpty(d.getMaterialCode())?"":d.getMaterialCode();
                    item.ShortText=d.getMaterialName()+(StrUtil.isNotEmpty(d.getMaterialSpec())?","+d.getMaterialSpec():"")+(StrUtil.isNotEmpty(d.getMaterialBrand())?","+d.getMaterialBrand():"");
                    item.OrderQuantity=d.getNum();
                    item.Currency=d.getCurrencyCode();
                    item.OrderUnit=d.getBasisUnit();
                    item.UnitPrice=d.getPrice();
                    item.TaxCode=d.getTaxRateCode();
                    item.TaxName=d.getTaxRateName();
                    item.TotalPrice=d.getPrice().multiply(d.getNum());
                    item.FactoryCode=d.getFactoryCode();
                    item.FactoryName=d.getFactoryName();
                    item.AssetSerialNumber=d.getId();
                    item.PurchaseNumber=StrUtil.isNotEmpty(d.getPurchaseCode())?d.getPurchaseCode():"";
                    item.Req_DeptNDame=d.getTeamName();
//                    item.DemanderName=contract.getContractDemandUser();
                    item.DemanderName=d.getRequireName();

                    DictDTO dictDTO = contractPayBootItemCache.get(d.getDriverAsset());
                    item.CustomerCode = StrUtil.isNotEmpty(d.getCustomerCode())?(d.getCustomerCode()+"_"+d.getCustomerName()):"";
                    item.DrivingFactors= ObjectUtil.isNotNull(dictDTO)?(d.getDriverAsset()+"_"+dictDTO.getName()):"";
//                    item.CostCenter = ObjectUtil.isNotNull(applyBillDetail)&&StrUtil.isNotEmpty(applyBillDetail.getCostCenterCode())?(applyBillDetail.getCostCenterCode()+"_"+applyBillDetail.getCostCenterName()):"";
                    item.CostCenter = StrUtil.isNotEmpty(d.getCostCenterCode())?(d.getCostCenterCode()+"_"+d.getCostCenterName()):"";
                    items.add(item);
                });
                //关联流程去重
                List<Map<String, String>> resultMapList = new ArrayList<>();
                Set<String> seen = new HashSet<>();
                for (Map<String, String> map : mapList) {
                    String docId = map.get("docId") ;
                    if (seen.add(docId)) {
                        resultMapList.add(map);
                    }
                }
                head.RelevanceFile=JSON.toJSONString(resultMapList);
            }
            Map map = new HashMap();
            map.put("item",items);
            oa.setItem(map);
        }else{
            List<OaFileParamDTO> StampFileLists = new ArrayList<>();
            List<ContractOA.MroItem> items = new ArrayList<>();
            head.SRMToS=ContractConst.BUSINESS_MRO;
            head.UnitCode=contract.getContractCompanyCode();
            head.UnitName=contract.getContractCompanyName();
            //合同文件
            head.Attachments=JSON.toJSONString(lists);
            //盖章文件错误，需要将明细行里的文件拼接成多个文件
            //  head.StampFile=JSON.toJSONString(signLists);
            head.SupplierFullName=contract.getContractSupplierName();
            head.SupplierCode=contract.getContractSupplierCode();
            if(!CollectionUtils.isEmpty(mros)) {
                mros.stream().forEach(d -> {
                    ContractOA.MroItem item = new ContractOA.MroItem();
                    item.FileName=d.getName();
                    item.Share=d.getNum();
                    String dDateTime = d.getSignTime().format(formatter1);
                    item.MyHead=d.getOurPeople();
                    item.TargetHead=d.getOtherPeople();
//2024-11-24注释非mro合同文件不取明细附件
//                    String fileIds = String.valueOf(d.getFileId());
//                    if (!StringUtils.isEmpty(fileIds)) {
//                        List<FileResposePreviewCDTO> previewDTOS = fileClient.getPreviewUrl(Arrays.asList(fileIds.split(",")));
//                        final OaFileParamDTO build = OaFileParamDTO.builder().url(previewDTOS.get(0).getPreviewUrl())
//                                .fileName(previewDTOS.get(0).getFileName()).downloadUrl(previewDTOS.get(0).getDownloadUrl()).build();
//                        item.Attachments=JSON.toJSONString(build);
//                        StampFileLists.add(build);
//                    }
                    item.ContractAmount=d.getAmount();
                    item.Remark="";
                    item.SigningDate=dDateTime;
                    items.add(item);
                });
            }
            //遍历明细，将附件拼接在一起
            if(!CollectionUtils.isEmpty(signFileLists)){
                head.StampFile=JSON.toJSONString(signFileLists);
            }
            if(!CollectionUtils.isEmpty(signLists)){
                head.StampFile=JSON.toJSONString(signLists);
            }
            //盖章后附件 2024-11-24qzc调整
//            head.StampFile=JSON.toJSONString(lists);
            Map map = new HashMap();
            map.put("item",items);
            oa.setItem(map);

        }
        head.contractApplyContent= contract.getContractApplyContent();
        head.ContractTypeName=contract.getContractType();
        if(!StringUtils.isEmpty(contract.getContractCover())){
            head.ContractCover=subMap.get(contract.getContractCover());
        }

        head.ContractAmount=contract.getContractAmount();
        head.AmountWoeds=contract.getContractAmountCapital();
        head.ElectronicSeal=contract.getIsSeal();
        oa.setHead(head);
        ApiResult result = null;
        if(contract.getIsMro().equals(1)){
            result = contractOaClient.saveContractTOOA(oa);
        }else{
            result = contractOaClient.saveMroTOOA(oa);
        }
        if(result.getCode().equals(RestCode.SAP_SUCCESS.getCode())){
            contract.setContractState(ContractConst.STATUE_PASS_OA);
        }
        contract.setOaCode(result.getCode());
        contract.setOaMsg(result.getMessage());
        contract.setOaProcessId(String.valueOf(result.getData()));
        contractService.updateById(contract);
        //提交审批 -  根据合同明细中采购申请单号、行号，将采购申请明细表中 transfer_status =  4；
        if(!CollectionUtils.isEmpty(details)){
            List<Long> detailIds = new ArrayList<>();
            for (ContractDetail detail : details) {
                PurchaseApplyBillDetailClientDTO applyBillDetail = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(detail.getPurchaseCode(),detail.getItemCode());
                if (ObjectUtil.isNotNull(applyBillDetail)){
                    detailIds.add(applyBillDetail.getId());
                }

            }
            purchaseApplyBillDetailClient.updatePuchaseMethode(null,4,detailIds);
        }
        return result;

    }

    @Override
    public ApiResult getPayBillByKm(String payId, String oaApplyId) {

        List<DictDTO> subs = dictClient.getDicByType("pay_mode");
        List<DictDTO> type = dictClient.getDicByType("contractPayCategory");
        Map<String, String> subMap = subs.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1,key2)->key2));
        Map<String, String> typeMap = type.stream().collect(Collectors.toMap(DictDTO::getCode,DictDTO::getName,(key1,key2)->key2));

        ContractPay pay = contractPayService.getById(payId);

        List<ContractDetail> details = contractDetailService.list(new LambdaQueryWrapper<ContractDetail>().eq(ContractDetail::getContractCode,pay.getContractCode())
                .eq(ContractDetail::getDeleteFlag,DelFlag.NORMAL.getStatus()));

        Contract contract = contractService.getOne(new LambdaQueryWrapper<Contract>().eq(Contract::getContractCode,pay.getContractCode()));

        //List<ContractPayOrder> payOrders = payOrderService.list(new LambdaQueryWrapper<ContractPayOrder>().eq(ContractPayOrder::getPayId,payId).eq(ContractPayOrder::getDeleteFlag,DelFlag.NORMAL.getStatus()));
        List<ContractPayType> payTypes = payTypeService.list(new LambdaQueryWrapper<ContractPayType>().eq(ContractPayType::getPayId,payId).eq(ContractPayType::getDeleteFlag,DelFlag.NORMAL.getStatus()));

        ContractPayOA payOA = new ContractPayOA();

        ContractPayOA.Head head = new ContractPayOA.Head();
        ContractPayOA.Item item = new ContractPayOA.Item();
        List<ContractPayOA.PurchaseOrderItem> purchaseOrderItem = new ArrayList<>();
        List<ContractPayOA.PaymentItem> paymentItem = new ArrayList<>();

        head.ProcessId=oaApplyId;
        head.SRMToS="10";
        head.Applicant=pay.getCreateUserCode();

        LocalDate dateTime = pay.getCreateTime();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDateTime = dateTime.format(formatter);
        head.ApplyDate=formattedDateTime;
        head.CompanyCode=pay.getPayOrgCode();
        head.CompanyName=pay.getPayOrgName();
        String code = "";
//        if(!StringUtils.isEmpty(pay.getSettlementMethod())){
//            code = subMap.get(pay.getSettlementMethod());
//            head.setPayMethod(code);
//        }

        head.PayMethod=StrUtil.isNotEmpty(pay.getSettlementMethod())?pay.getSettlementMethod():"";

        head.PayeeName=pay.getPayeeName();
        head.SupplierCode=pay.getPayeeCode();
        head.BankNo=pay.getBankCode();
        head.SwiftCode=pay.getBankSwiftCode();
        head.Currency=pay.getPayCurrency();
        if(pay.getPayCurrency().equals("人民币")){
            head.Currency = "CNY";
        }
        if(pay.getPayCurrency().equals("美元")){
            head.Currency = "USD";
        }
        if(pay.getPayCurrency().equals("港元")){
            head.Currency = "HKD";
        }
        head.BankName=pay.getBankName();
        head.PayeeAccount=pay.getBankAccount();
        head.SapOrderPayment=pay.getSapPayType();
        head.AdvancePayment=pay.getPayType()==1?"是":"否";
        head.ContractAmountPrepaid=pay.getPayeeAmount();
        head.ContractAmount=pay.getContractAmount();
        head.CostAscriptionDept=pay.getBelongDeptName();

        if(!CollectionUtils.isEmpty(details)) {
            List<Map> mapList = new ArrayList<>();
            AtomicReference<Boolean> flag = new AtomicReference<>(false);
            details.stream().forEach(d -> {
                if(!StringUtils.isEmpty(d.getPurchaseCode())){
                    flag.set(true);
//                    Map map = new HashMap();
//                    map.put("subject", StringUtils.isEmpty(d.getPurchaseCode()) ? "关联文档" : d.getPurchaseCode());
//                    map.put("docId", contract.getOaProcessId());
//                    mapList.add(map);
                }
            });
            //if(!flag.get()){
            Map map = new HashMap();
            map.put("subject", StringUtils.isEmpty(contract.getContractTitle()) ? "关联文档" : contract.getContractTitle());
            map.put("docId", contract.getOaProcessId());
            mapList.add(map);
            //}

            head.RelatedProcess=JSON.toJSONString(mapList);
        }
        if (!StringUtils.isEmpty(pay.getAccepProcessData())){
            head.RelatedYanShou=pay.getAccepProcessData();
        }
        if (!StringUtils.isEmpty(pay.getMuJuProcessData())){
            head.RelatedMuJu=pay.getMuJuProcessData();
        }
        if (!StringUtils.isEmpty(pay.getPurchaseProcessData())){
            head.RelatedPurchase=pay.getPurchaseProcessData();
        }
        head.TotalAmount=pay.getTotalAmount();
        head.ExcludingTaxAmount=pay.getTotalAmountNo();
        head.TotalTaxAmount=pay.getTaxAmount();
        head.PaymentAmountWords=pay.getAmountCapital();


        String files = pay.getPayFiles();
        List<String> previews = new ArrayList<>();
        List<OaFileParamDTO> lists = new ArrayList<>();
        if(!StringUtils.isEmpty(files)){
            List<FileResposePreviewCDTO>  previewDTOS = fileClient.getPreviewUrl(Arrays.asList(files.split(",")));
            previewDTOS.stream().forEach(a->{
                final OaFileParamDTO build = OaFileParamDTO.builder().url(a.getPreviewUrl())
                        .fileName(a.getFileName()).downloadUrl(a.getDownloadUrl()).build();
                lists.add(build);
            });
            head.Attachment=JSON.toJSONString(lists);
        }


        if(pay.getSapPayType().equals(ContractConst.SAPPAYTYPE)){
//            PurchaseApplyBillDetailClientDTO applyBillDetail = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(details.get(0).getPurchaseCode(),details.get(0).getItemCode());
            ContractPayOA.PurchaseOrderItem orderItem = new ContractPayOA.PurchaseOrderItem();
            orderItem.setPurchaseOrder(pay.getOrderCode());
            if(!Objects.isNull(details.get(0))){
                orderItem.setUser(StrUtil.isNotEmpty(details.get(0).getRequireName())?details.get(0).getRequireName():"");
                orderItem.setCostCenterCode(StrUtil.isNotEmpty(details.get(0).getCostCenterCode())?details.get(0).getCostCenterCode():"");
                orderItem.setCostCenterName(StrUtil.isNotEmpty(details.get(0).getCostCenterName())?details.get(0).getCostCenterName():"");
            }else{
                orderItem.setUser("");
                orderItem.setCostCenterCode("");
                orderItem.setCostCenterName("");
            }
            orderItem.setPaymentAmount(pay.getTotalAmount());
            orderItem.setPayableAmount(pay.getPaymentProgress());
            orderItem.setUnpaidAmount(pay.getUnpaidAmount());
            orderItem.setProcurementSummary(pay.getBz());
            purchaseOrderItem.add(orderItem);
            item.setPurchaseOrderItem(purchaseOrderItem);
        }else{
            payTypes.stream().forEach(a->{
                ContractPayOA.PaymentItem mentItem = new ContractPayOA.PaymentItem();
                String typeCode = "";
                if(!ObjectUtils.isEmpty(a.getType())){
                    typeCode = typeMap.get(a.getType().toString());
                    mentItem.ReimburseType  =typeCode;
                }
                mentItem.BusinessDesc=a.getBz();
                mentItem.Amount=a.getAmount();
                mentItem.User=a.getUser();
                mentItem.InternalOrder="";
                mentItem.ProjectNo= StringUtils.isEmpty(a.getCode()) ? "": a.getCode();//项目编号"";
                mentItem.Customer=a.getServiceUser();
                mentItem.CustomerCode=a.getServiceUserCode();
                mentItem.DrivingFactors=a.getDriveBz();
                mentItem.FixedAssetCode=a.getAssetCode();
                mentItem.CostCenter=a.getCostCenterName(); //成本中心(显示值)
                mentItem.CostCenterCode=a.getCostCenterCode(); //成本中心实际值

                paymentItem.add(mentItem);
            });
            item.setPaymentItem(paymentItem);
        };
        payOA.setHead(head);
        payOA.setItem(item);

        ApiResult result = contractOaClient.saveConntractPay(payOA);
        result.setCode("S");
        //状态 0 待提交  1审批中 2 通过 3 驳回
        if(result.getCode().equals(RestCode.SAP_SUCCESS.getCode())){
            pay.setPayState(ContractConst.STATUE_PASS_PAY_OA);
        }
        pay.setOaCode(result.getCode());
        pay.setOaMsg(result.getMessage());
        pay.setOaProcessId(String.valueOf(result.getData()));
        contractPayService.updateById(pay);
        return result;
    }

    @Override
    public PageView getOaProcessList(ProcessListQuery processListQuery) {
        OaProcessListQuery oa = new OaProcessListQuery();
        oa.setPage(processListQuery.getPage());
        oa.setRows(processListQuery.getRows());
        BasePageQuery query = new BasePageQuery();
        query.setPage(oa.getRows());
        query.setRows(oa.getPage());
        final Page<Contract> page = PageUtil.toPage(query);
        List<OaProcessDTO> oaProcessDTOS = null;
        OaProcessListQuery.Head head = new OaProcessListQuery.Head();
        head.setPageNo(oa.getPage());
        head.setPageSize(oa.getRows());
        head.setProcessType(processListQuery.getProcessType());
        head.setPersonnelName(processListQuery.getPersonnelName());
        head.setProcessName(processListQuery.getProcessName());
        oa.setHead(head);
        ApiResult<JSONObject> result = contractOaClient.getOaProcessListPage(oa);
        if(result.getCode().equals(RestCode.SAP_SUCCESS.getCode())){
            JSONArray ja = (JSONArray) result.getData().get("rows");
            Integer total= (Integer) result.getData().get("total");
            return PageUtil.getPV(ja, total);
        }else{
            return PageUtil.getPV(Lists.newArrayList(), 0);
        }

    }

    @Override
    public void sendSign(String conId) {
        Contract contract = contractService.getById(conId);
//
//        //获取公司对应的 E签宝信息
//        DigitalSealConfigDTO sealConfigDTOS = contractService.selectESignDetail(contract.getContractCompanyCode(),contract.getContractSealType());
//
//        if(sealConfigDTOS==null){
//            throw new DaoException("未查询到公司对应的印章信息!");
//        }
//
//        // 构建请求Body体
//        SubjectDTO subjectDTO = new SubjectDTO();
//        subjectDTO.setBusinessNo("contract");
//        subjectDTO.setSubject(contract.getContractTitle());
//        subjectDTO.setBusinessTypeCode(businessTypeCode);
//        subjectDTO.setReadComplete(1);
//        subjectDTO.setRemark("");
//        subjectDTO.setSignNotifyUrl(callbackUrl);
////        subjectDTO.setRedirectUrl("www.baidu.com");
//
//        SubjectDTO.InitiatorInfo initiatorInfo = new SubjectDTO.InitiatorInfo();
//        initiatorInfo.setUserCode(sealConfigDTOS.getSignerAccount()); // 发起人 编码
//        initiatorInfo.setOrganizationCode(sealConfigDTOS.getSignerOrgCode()); // 发起人 组织编码
//        subjectDTO.setInitiatorInfo(initiatorInfo);
//
//        //流程文档信息
//        List<SubjectDTO.SignFiles> signFiles = new ArrayList<>();
//        SubjectDTO.SignFiles signFile = new SubjectDTO.SignFiles();
//        signFile.setFileKey(contract.getFileKey());
//        signFiles.add(signFile);
//        subjectDTO.setSignFiles(signFiles);
//
//
//        SubjectDTO.ManualConfig manualConfig = new SubjectDTO.ManualConfig();
//        manualConfig.setStartMode(0);
//        manualConfig.setFinishMode(0);
//        subjectDTO.setManualConfig(manualConfig);
//
//        //签章顺序 1 对方先签  2我方先签  3单方签
//        String signOrder = contract.getContractSignOrder();
//        //签章类型  合同章 公章
////        String sealType = contract.getContractSealType();
//
//        Boolean f = true;
//        Integer orderOne = 1;
//        Integer orderTow = 2;
//        if(signOrder.equals("3")){
//            f = false;
//        }
//
//        List<SubjectDTO.SignerInfos> signerInfos = new ArrayList<>();
//
//        //设置甲方信息
//        SubjectDTO.SignerInfos signerInfoJf = new SubjectDTO.SignerInfos();
//        signerInfoJf.setUserType(1);
//        signerInfoJf.setUserCode(sealConfigDTOS.getSignerAccount());
//        signerInfoJf.setOrganizationCode(sealConfigDTOS.getSignerOrgCode());
//        //指定印章类型
////        signerInfoJf.setSealTypeCode("PERSONNEL");
//
//        if(f){
//            //设置 签章顺序
//            if(signOrder.equals("1")){
//                signerInfoJf.setSignMode(0);
//                signerInfoJf.setSignNode(orderTow);
//                signerInfoJf.setSignOrder(orderTow);
//            }else if(signOrder.equals("2")){
//                signerInfoJf.setSignMode(0);
//                signerInfoJf.setSignNode(orderOne);
//                signerInfoJf.setSignOrder(orderOne);
//            }
//        }else{
//            //设置 签章顺序
//            signerInfoJf.setSignMode(0);
//            signerInfoJf.setSignNode(orderOne);
//            signerInfoJf.setSignOrder(orderOne);
//        }
//
//        //签署任务信
//        List<SubjectDTO.SealInfos> sealInfosJf = new ArrayList<>();
//        SubjectDTO.SealInfos sealInfoJf = new SubjectDTO.SealInfos();
//        sealInfoJf.setFileKey(contract.getFileKey());
//        List<SubjectDTO.SignConfigs> signConfigsJf = new ArrayList<>();
//        SubjectDTO.SignConfigs signConfigJf = new SubjectDTO.SignConfigs();
//
//        //设置印章
//        signConfigJf.setSealId(sealConfigDTOS.getSealCode());
//        //指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章
//        signConfigJf.setSignatureType("COMMON-SEAL");
//
//        //设置关键字
//        SubjectDTO.KeywordInfo keywordInfoJf = new SubjectDTO.KeywordInfo();
//        keywordInfoJf.setKeywordIndex(-1);
//        keywordInfoJf.setKeyword("甲方");
//        signConfigJf.setKeywordInfo(keywordInfoJf);
//        signConfigJf.setSignFieldType(0);
//        signConfigJf.setAllowMove(0);
//        signConfigJf.setSignType("KEYWORD-SIGN");
//        sealInfoJf.setSignConfigs(signConfigsJf);
//        signConfigsJf.add(signConfigJf);
//        sealInfosJf.add(sealInfoJf);
//        signerInfoJf.setSealInfos(sealInfosJf);
//        signerInfos.add(signerInfoJf);
//
//        if(f){
//            SubjectDTO.SignerInfos signerInfoYf = new SubjectDTO.SignerInfos();
//            signerInfoYf.setUserType(2);
//            signerInfoYf.setUserCode(contract.getContractSupplierCode());
//            signerInfoYf.setCustomOrgNo(contract.getContractSupplierCode());
//            //指定印章类型
//            signerInfoYf.setSealTypeCode("");
//
//            if(signOrder.equals("1")){
//                signerInfoYf.setSignMode(0);
//                signerInfoYf.setSignNode(orderOne);
//                signerInfoYf.setSignOrder(orderOne);
//            }else if(signOrder.equals("2")){
//                signerInfoYf.setSignMode(0);
//                signerInfoYf.setSignNode(orderTow);
//                signerInfoYf.setSignOrder(orderTow);
//            }
////            签署任务信
//            List<SubjectDTO.SealInfos> sealInfosYf = new ArrayList<>();
//            SubjectDTO.SealInfos sealInfoYf = new SubjectDTO.SealInfos();
//
//            sealInfoYf.setFileKey(contract.getFileKey());
//            List<SubjectDTO.SignConfigs> signConfigsYf = new ArrayList<>();
//            SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
//            signConfigYf.setSignatureType("COMMON-SEAL");
//            //设置关键字
//            SubjectDTO.KeywordInfo keywordInfoYf = new SubjectDTO.KeywordInfo();
//            keywordInfoYf.setKeywordIndex(-1);
//            keywordInfoYf.setKeyword("乙方");
//            signConfigYf.setKeywordInfo(keywordInfoYf);
//            signConfigYf.setSignFieldType(0);
//            signConfigYf.setAllowMove(0);
//            signConfigYf.setSignType("KEYWORD-SIGN");
//            sealInfoYf.setSignConfigs(signConfigsYf);
//            signConfigsYf.add(signConfigYf);
//            sealInfosYf.add(sealInfoYf);
//            signerInfoYf.setSealInfos(sealInfosYf);
//            signerInfos.add(signerInfoYf);
//        }
//
//        subjectDTO.setSignerInfos(signerInfos);
//
//        // 请求Body体数据
//        String reqBodyData = JSONObject.toJSONString(subjectDTO);
//        log.info("发起签署流程接口调用参数{}",reqBodyData);
//        System.out.println("请求信息： " + reqBodyData);
//
//        // 构建参与请求签名计算的明文
//        String plaintext = reqBodyData;
//        // 计算请求签名值
//        String reqSignature = SignUtils.sign256(plaintext, projectsecret);
//        // 构建请求头
//
//        LinkedHashMap<String, String> header = new LinkedHashMap<>();
//        // 构建待签名字符串
//        String contentType = "application/json; charset=UTF-8";
//        String accept = "*/*";
//        header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)");
//        header.put("X-timevale-signature", reqSignature);
//        header.put("X-timevale-project-id", projectid);
//        header.put("Accept", accept);
//        header.put("Content-Type", contentType);
//        header.put("Content-Length", "1123");
//
//        String getInnerOrganizationsDetailApi = "/esign-signs/v1/signFlow/createAndStart";
//        String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;
//        //发送POST请求
//        String result = null;
//        try {
//            result = HTTPHelper.sendPOST1(uploadApiUrl, reqBodyData, header, "UTF-8");
//            log.info("发起签署流程接口返回结果{}",JSON.toJSONString(result));
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//        System.out.println(JSON.toJSONString("result----"+result));
//        ApiResult json = JSON.parseObject(result,ApiResult.class);
//        if(json.getCode().equals(RestCode.MES_SUCCESS.getCode())){
//            JSONObject dataJson = (JSONObject)json.getData();;
//            contractService.update(new LambdaUpdateWrapper<Contract>()
//                    .set(Contract::getSignFlowId,dataJson.getString("signFlowId"))
//                    .set(Contract::getSignFlowStatus, dataJson.getString("signFlowStatus"))
//                    .set(Contract::getContractSignFileStatue,"已发起签署")
//                    .eq(Contract::getId,conId));
//        }else{
//            throw new DaoException(json.getMessage());
//        }
//
//
////        ApiResult result = signClient.sendSign(header,subjectDTO);
////        System.out.println("result-=-=-=-=-"+result);
////        if(result.getCode().equals(RestCode.MES_SUCCESS.getCode())){
////            JSONObject dataJson = (JSONObject)result.getData();;
////            contractService.update(new LambdaUpdateWrapper<Contract>()
////                    .set(Contract::getSignFlowId,dataJson.getString("signFlowId"))
////                    .set(Contract::getSignFlowStatus, dataJson.getString("signFlowStatus"))
////                    .set(Contract::getContractSignFileStatue,"已发起签署")
////                    .eq(Contract::getId,conId));
////        }else{
////            throw new DaoException(result.getMessage());
////        }

        final ContractSendSignDTO contractSendSignDTO = ContractSendSignDTO.builder()
                .title("合同编号："+contract.getContractCode())
                .companyCode(contract.getContractCompanyCode())
                .supplierCode(contract.getContractSupplierCode())
                .fileKey(contract.getFileKey())
                .contractSignOrder(contract.getContractSignOrder()).build();

        ContractSendSignResultDTO resultDTO = sendSignClient(contractSendSignDTO, SignProcessType.CONTRACT);
        contractService.update(new LambdaUpdateWrapper<Contract>()
                .set(Contract::getSignFlowId,resultDTO.getSignFlowId())
                .set(Contract::getSignFlowStatus, resultDTO.getSignFlowStatus())
                .set(Contract::getContractSignFileStatue,"已发起电子印章签署")
                .eq(Contract::getId,conId));

    }

    public ContractSendSignResultDTO sendSignClient(ContractSendSignDTO contractSendSignDTO, SignProcessType signProcessType){
//        Contract contract = contractService.getById(conId);

        //获取公司对应的 E签宝信息
        DigitalSealConfigDTO sealConfigDTOS = contractService.selectESignDetail(contractSendSignDTO.getCompanyCode(), String.valueOf(signProcessType.getContractSealType()));

        if(sealConfigDTOS==null){
            throw new DaoException("未查询到公司对应的印章信息!");
        }

        // 构建请求Body体
        SubjectDTO subjectDTO = new SubjectDTO();
        subjectDTO.setBusinessNo(signProcessType.getBusinessNo());
        subjectDTO.setSubject(contractSendSignDTO.getTitle());
        subjectDTO.setBusinessTypeCode(businessTypeCode);
        subjectDTO.setReadComplete(1);
        subjectDTO.setRemark("");
        subjectDTO.setSignNotifyUrl(callbackUrl);
//        subjectDTO.setRedirectUrl("www.baidu.com");

        SubjectDTO.InitiatorInfo initiatorInfo = new SubjectDTO.InitiatorInfo();
        initiatorInfo.setUserCode(sealConfigDTOS.getSignerAccount()); // 发起人 编码
        initiatorInfo.setOrganizationCode(sealConfigDTOS.getSignerOrgCode()); // 发起人 组织编码
        subjectDTO.setInitiatorInfo(initiatorInfo);

        //流程文档信息
        List<SubjectDTO.SignFiles> signFiles = new ArrayList<>();
        SubjectDTO.SignFiles signFile = new SubjectDTO.SignFiles();
        signFile.setFileKey(contractSendSignDTO.getFileKey());
        signFiles.add(signFile);
        subjectDTO.setSignFiles(signFiles);
        SubjectDTO.ManualConfig manualConfig = new SubjectDTO.ManualConfig();
        manualConfig.setStartMode(0);
        manualConfig.setFinishMode(0);
        subjectDTO.setManualConfig(manualConfig);

        //签章顺序 1 对方先签  2我方先签  3单方签
        String signOrder = contractSendSignDTO.getContractSignOrder();
        //签章类型  合同章 公章
//        String sealType = contract.getContractSealType();

        Boolean f = true;
        Integer orderOne = 1;
        Integer orderTow = 2;
        if(signOrder.equals("3")){
            f = false;
        }

        List<SubjectDTO.SignerInfos> signerInfos = new ArrayList<>();

        //设置甲方信息
        SubjectDTO.SignerInfos signerInfoJf = new SubjectDTO.SignerInfos();
        signerInfoJf.setUserType(1);
        signerInfoJf.setUserCode(sealConfigDTOS.getSignerAccount());
        signerInfoJf.setOrganizationCode(sealConfigDTOS.getSignerOrgCode());
        //指定印章类型
//        signerInfoJf.setSealTypeCode("PERSONNEL");

        if(f){
            //设置 签章顺序
            if(signOrder.equals("1")){
                signerInfoJf.setSignMode(0);
                signerInfoJf.setSignNode(orderTow);
                signerInfoJf.setSignOrder(orderTow);
            }else if(signOrder.equals("2")){
                signerInfoJf.setSignMode(0);
                signerInfoJf.setSignNode(orderOne);
                signerInfoJf.setSignOrder(orderOne);
            }
        }else{
            //设置 签章顺序
            signerInfoJf.setSignMode(0);
            signerInfoJf.setSignNode(orderOne);
            signerInfoJf.setSignOrder(orderOne);
        }

        //签署任务信
        List<SubjectDTO.SealInfos> sealInfosJf = new ArrayList<>();
        SubjectDTO.SealInfos sealInfoJf = new SubjectDTO.SealInfos();
        sealInfoJf.setFileKey(contractSendSignDTO.getFileKey());
        List<SubjectDTO.SignConfigs> signConfigsJf = new ArrayList<>();
        SubjectDTO.SignConfigs signConfigJf = new SubjectDTO.SignConfigs();

        //设置印章
        signConfigJf.setSealId(sealConfigDTOS.getSealCode());
        //指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章
        signConfigJf.setSignatureType("COMMON-SEAL");

        //设置关键字
        SubjectDTO.KeywordInfo keywordInfoJf = new SubjectDTO.KeywordInfo();
        keywordInfoJf.setKeywordIndex(-1);
        keywordInfoJf.setKeyword("甲方");
        signConfigJf.setKeywordInfo(keywordInfoJf);
        signConfigJf.setSignFieldType(0);
        signConfigJf.setAllowMove(0);
        signConfigJf.setSignType("KEYWORD-SIGN");
        sealInfoJf.setSignConfigs(signConfigsJf);
        signConfigsJf.add(signConfigJf);
        sealInfosJf.add(sealInfoJf);
        signerInfoJf.setSealInfos(sealInfosJf);
        signerInfos.add(signerInfoJf);

        if(f){
            SubjectDTO.SignerInfos signerInfoYf = new SubjectDTO.SignerInfos();
            signerInfoYf.setUserType(2);
            SupplierContactsDTO supplierContactsDTO = supplierClient.getDefaultContact(contractSendSignDTO.getSupplierCode(),"10");
            if (ObjectUtil.isNull(supplierContactsDTO)){
                throw new DaoException("未查询到供应商用户编号!");
            }
            if (StrUtil.isEmpty(supplierContactsDTO.getContactsTel())){
                throw new DaoException("未查询到供应商用户编号!");
            }
//            signerInfoYf.setUserCode(contractSendSignDTO.getSupplierCode());
            signerInfoYf.setUserCode(supplierContactsDTO.getContactsTel());
            signerInfoYf.setCustomOrgNo(contractSendSignDTO.getSupplierCode());
            //指定印章类型
            signerInfoYf.setSealTypeCode("");

            if(signOrder.equals("1")){
                signerInfoYf.setSignMode(0);
                signerInfoYf.setSignNode(orderOne);
                signerInfoYf.setSignOrder(orderOne);
            }else if(signOrder.equals("2")){
                signerInfoYf.setSignMode(0);
                signerInfoYf.setSignNode(orderTow);
                signerInfoYf.setSignOrder(orderTow);
            }
//            签署任务信
            List<SubjectDTO.SealInfos> sealInfosYf = new ArrayList<>();
            SubjectDTO.SealInfos sealInfoYf = new SubjectDTO.SealInfos();

            sealInfoYf.setFileKey(contractSendSignDTO.getFileKey());
            List<SubjectDTO.SignConfigs> signConfigsYf = new ArrayList<>();
            SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
            signConfigYf.setSignatureType("COMMON-SEAL");
            //设置关键字
            SubjectDTO.KeywordInfo keywordInfoYf = new SubjectDTO.KeywordInfo();
            keywordInfoYf.setKeywordIndex(-1);
            keywordInfoYf.setKeyword("乙方");
            signConfigYf.setKeywordInfo(keywordInfoYf);
            signConfigYf.setSignFieldType(0);
            signConfigYf.setAllowMove(0);
            signConfigYf.setSignType("KEYWORD-SIGN");
            sealInfoYf.setSignConfigs(signConfigsYf);
            signConfigsYf.add(signConfigYf);
            sealInfosYf.add(sealInfoYf);
            signerInfoYf.setSealInfos(sealInfosYf);
            signerInfos.add(signerInfoYf);
        }

        subjectDTO.setSignerInfos(signerInfos);

        // 请求Body体数据
        String reqBodyData = JSONObject.toJSONString(subjectDTO);
        log.info("发起签署流程接口调用参数{}",reqBodyData);
        System.out.println("请求信息： " + reqBodyData);

        // 构建参与请求签名计算的明文
        String plaintext = reqBodyData;
        // 计算请求签名值
        String reqSignature = SignUtils.sign256(plaintext, projectsecret);
        // 构建请求头

        LinkedHashMap<String, String> header = new LinkedHashMap<>();
        // 构建待签名字符串
        String contentType = "application/json; charset=UTF-8";
        String accept = "*/*";
        header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)");
        header.put("X-timevale-signature", reqSignature);
        header.put("X-timevale-project-id", projectid);
        header.put("Accept", accept);
        header.put("Content-Type", contentType);
        header.put("Content-Length", "1123");

        String getInnerOrganizationsDetailApi = "/esign-signs/v1/signFlow/createAndStart";
        String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;
        //发送POST请求
        String result = null;
        try {
            result = HTTPHelper.sendPOST1(uploadApiUrl, reqBodyData, header, "UTF-8");
            log.info("发起签署流程接口返回结果{}",JSON.toJSONString(result));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            //调用方日志
            LogManager.me().executeLog(ApiLogTaskFactory.saveCallLog("sendSignFile", "一步发起签署接口",
                    ThirdSysType.SIGN.getType(),
                    reqBodyData,
                    result,
                    "",
                    LocalDateTime.now()
            ));
        }
        System.out.println(JSON.toJSONString("result----"+result));
        ApiResult json = JSON.parseObject(result,ApiResult.class);
        if(json.getCode().equals(RestCode.MES_SUCCESS.getCode())){
            JSONObject dataJson = (JSONObject)json.getData();;
            return ContractSendSignResultDTO.builder().signFlowId(dataJson.getString("signFlowId")).signFlowStatus(dataJson.getString("signFlowStatus")).build();
        }else{
            throw new DaoException("e签宝接口返回错误："+json.getMessage());
        }

    }

    @Override
    public DigitalSealConfigDTO selectESignDetailClient(String companyCode, String sealType) {
        return contractService.selectESignDetail(companyCode, sealType);
    }

    @Override
    public List<Map<String,String>> detailImport(MultipartFile file,Integer isSap) {
        try {
            List<Map<String,String>> dataList = EasyExcelImportUtils.parseExcelToData(file.getInputStream(), 2);
            //税率
            final List<TaxDTO> taxDTOS = taxClient.getAll();
            final Map<String, TaxDTO> taxCache = taxDTOS.stream().collect(Collectors.toMap(TaxDTO::getTaxName, a -> a));
            final Set<String> taxNames = taxCache.keySet();

            for (Map<String,String> map : dataList){
                if (StrUtil.isEmpty(map.get("subjectCode"))){
                    throw new DaoException("请选择科目");
                }
                if (StrUtil.isNotEmpty(map.get("subjectCode"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(ObjectUtil.isNotNull(isSap)&&isSap==1? DictCode.CONTRACT_ITEM_SUBJECT_SAP.getCode():DictCode.CONTRACT_ITEM_SUBJECT.getCode(),map.get("subjectCode"));
                    map.put("subjectCode",dictDTO.getCode());
                }
                if (StrUtil.isEmpty(map.get("materialName"))){
                    throw new DaoException("物料名称必填");
                }
                if (StrUtil.isEmpty(map.get("basisUnit"))){
                    throw new DaoException("物料单位必填");
                }
                if (StrUtil.isNotEmpty(map.get("basisUnit"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(DictCode.UNIT.getCode(),map.get("basisUnit"));
                    map.put("basisUnit",dictDTO.getCode());
                }
                if (StrUtil.isEmpty(map.get("price"))){
                    throw new DaoException("单价(含税)必填");
                }
                if (StrUtil.isNotEmpty(map.get("price"))){
                    try {
                        new BigDecimal(map.get("price"));
                    }catch (Exception e){
                        throw new DaoException(StrUtil.format("单价(含税)：{}格式不正确",map.get("price")));
                    }
                }
                if (StrUtil.isNotEmpty(map.get("materialGroupCode"))){
                    ProductGroupDTO productGroupDTO = productGroupClient.getByCode(map.get("materialGroupCode"));
                    if (ObjectUtil.isNull(productGroupDTO)){
                        throw new DaoException(StrUtil.format("物料组编码：{}在系统中不存在",map.get("materialGroupCode")));
                    }
                    map.put("materialGroupName",productGroupDTO.getMaterialDesc());
                }
                if (StrUtil.isNotEmpty(map.get("taxRateCode"))){
                    if (!taxNames.contains(map.get("taxRateCode"))) {
                        throw new DaoException(StrUtil.format("税码：{}在系统中不存在",map.get("taxRateCode")));
                    }
                    TaxDTO taxDTO = taxCache.get(map.get("taxRateCode"));
                    map.put("taxRateName",taxDTO.getTaxName());
                    map.put("taxRateCode",taxDTO.getTaxCode());
                }
                if (StrUtil.isEmpty(map.get("num"))){
                    throw new DaoException("需求数量必填");
                }
                if (StrUtil.isNotEmpty(map.get("num"))){
                    try {
                        new BigDecimal(map.get("num"));
                    }catch (Exception e){
                        throw new DaoException(StrUtil.format("需求数量：{}格式不正确",map.get("num")));
                    }
                }
//                if (StrUtil.isEmpty(map.get("purchaseCode"))){
//                    throw new DaoException("请购单号必填");
//                }
//                if (StrUtil.isEmpty(map.get("itemCode"))){
//                    throw new DaoException("请购单行号必填");
//                }
                if (StrUtil.isNotEmpty(map.get("purchaseCode"))&&StrUtil.isNotEmpty(map.get("itemCode"))){
                    PurchaseApplyBillDetailClientDTO purchaseApplyBillDetailClientDTO = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(map.get("purchaseCode"),map.get("itemCode"));
                    if (ObjectUtil.isNull(purchaseApplyBillDetailClientDTO)){
                        throw new DaoException(StrUtil.format("请购单编码：{}在系统中不存在",map.get("purchaseCode")));
                    }
                    map.put("itemCode",purchaseApplyBillDetailClientDTO.getItemCode());
                    map.put("teamName",StrUtil.isEmpty(map.get("teamName"))?purchaseApplyBillDetailClientDTO.getTeamName():map.get("teamName"));
                    map.put("requireName",StrUtil.isEmpty(map.get("requireName"))?purchaseApplyBillDetailClientDTO.getRequireName():map.get("requireName"));
                    map.put("costCenterCode",StrUtil.isEmpty(map.get("costCenterCode"))?purchaseApplyBillDetailClientDTO.getCostCenterCode():map.get("costCenterCode"));
                    map.put("costCenterName",StrUtil.isEmpty(map.get("costCenterName"))?purchaseApplyBillDetailClientDTO.getCostCenterName():map.get("costCenterName"));
                    map.put("driverAsset",purchaseApplyBillDetailClientDTO.getFactor());
                    if (StrUtil.isEmpty(map.get("customerCode"))){
                        map.put("customerCode",purchaseApplyBillDetailClientDTO.getCustomerCode());
                        map.put("customerName",purchaseApplyBillDetailClientDTO.getCustomerName());
                    }
                }
                if (StrUtil.isEmpty(map.get("factoryCode"))){
                    throw new DaoException("工厂编码必填");
                }
                if (StrUtil.isNotEmpty(map.get("factoryCode"))){
                    FactoryDTO factoryDTO = factoryClient.getByCode(map.get("factoryCode"));
                    if (ObjectUtil.isNull(factoryDTO)){
                        throw new DaoException(StrUtil.format("工厂编码：{}在系统中不存在",map.get("factoryCode")));
                    }
                    map.put("factoryName",factoryDTO.getName());
                }
                if (StrUtil.isNotEmpty(map.get("driverAsset"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(DictCode.CONTRACT_PAY_BOOT_ITEM.getCode(),map.get("driverAsset"));
                    if (ObjectUtil.isNotNull(dictDTO)){
                        map.put("driverAsset",dictDTO.getCode());
                    }
                }
                if (StrUtil.isEmpty(map.get("currencyCode"))){
                    throw new DaoException("币别必填");
                }
                if (StrUtil.isNotEmpty(map.get("currencyCode"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(DictCode.CURRENCY.getCode(),map.get("currencyCode"));
                    map.put("currencyCode",dictDTO.getCode());
                }
                if (StrUtil.isNotEmpty(map.get("customerCode"))){
                    CustomerInfoClientDTO customerInfoClientDTO = supplierClient.getCustomerInfoByCode(map.get("customerCode"));
                    if (ObjectUtil.isNull(customerInfoClientDTO)){
                        throw new DaoException(StrUtil.format("服务客户编码：{}在系统中不存在",map.get("customerCode")));
                    }
                    map.put("customerCode",customerInfoClientDTO.getCustomerCode());
                    map.put("customerName",customerInfoClientDTO.getCustomerName1());
                }
            }
            return dataList;
        } catch (IOException e) {
            throw new DaoException("读取Excel失败");
        }
    }

    @Override
    public void updateTime(List<String> idList, String deliveryDate, String invoiceTime) {
        for (String id : idList){
            ContractDetail contractDetail = contractDetailService.getById(id);
            contractDetail.setDeliveryDate(LocalDateTimeUtil.parse(deliveryDate,"yyyy-MM-dd"));
            contractDetail.setInvoiceTime(LocalDateTimeUtil.parse(invoiceTime,"yyyy-MM-dd HH:mm:ss"));
            contractDetailService.updateById(contractDetail);
        }
    }

    @Override
    public List<ContractDetailDTO> getDetailListByPurchaseCodeAndeItem(String billCode, String itemCode) {
        List<ContractDetail> contractDetail = contractDetailService.list(Wrappers.lambdaQuery(ContractDetail.class)
                .eq(ContractDetail::getPurchaseCode,billCode).eq(ContractDetail::getItemCode,itemCode)
                .eq(ContractDetail::getDeleteFlag,0));

         if(!CollectionUtils.isEmpty(contractDetail)){
             List<Long> ids = contractDetail.stream().map(ContractDetail::getContractId).collect(Collectors.toList());
             List<Contract> list = contractService.list(Wrappers.lambdaQuery(Contract.class)
                     .in(Contract::getId, ids)
                     .eq(Contract::getDeleteFlag, 0));
             if(!CollectionUtils.isEmpty(list)){
                 List<Long> collecteds = list.stream().map(Contract::getId).collect(Collectors.toList());
                 contractDetail = contractDetail.stream().filter(contractDetail1 -> collecteds.contains(contractDetail1.getContractId())).collect(Collectors.toList());
             }
         }
        return contractConvert.entitieToDTOList(contractDetail);
    }

    @Override
    public void cancelContract(String id) {
        contractService.update(new LambdaUpdateWrapper<Contract>().set(Contract::getContractState,7)
                .eq(Contract::getId,id)
        );
    }

    @Override
    public FinancialShareApiResultDTO submitContractToGx(String conId, String gxApplyId, String isTerminated) {

        Contract contract = contractService.getById(conId);
        String accessToken = financialShareUtil.getShareAccessToken();
        JSONObject reqBody = new JSONObject();
        JSONArray dataArray = new JSONArray();
        JSONObject dataItem = new JSONObject();
        //判断合同类型 及变更类型
        Boolean changeFlag = false;
        if("07".equals(contract.getContractType()) && contract.getChangeType().contains("03")){
            changeFlag = true;
        }
        // 添加基础字段
        dataItem.put("m4p4_powerchange", changeFlag);//是否权责变更
        dataItem.put("billno", contract.getContractCode());//合同编号
        dataItem.put("m4p4_billname", contract.getContractTitle());//合同名称

        dataItem.put("m4p4_contracttype", contract.getContractType());//合同类型
        dataItem.put("m4p4_isterminated", isTerminated);    // 是否终止[0:否, 1:是]
        dataItem.put("m4p4_ismro", Integer.valueOf(1).equals(contract.getIsMro())?true:false);//否MRO合同
        dataItem.put("m4p4_isesign", Integer.valueOf(1).equals(contract.getIsSeal())?true:false);//是否电子签章
        dataItem.put("m4p4_draftby",contract.getContractDraft());//合同拟定方
//        dataItem.put("m4p4_acceptdate", "2025-12-11");验收日期
        dataItem.put("m4p4_maincontno", contract.getAssociationContract());//关联主合同
        dataItem.put("m4p4_contamt",contract.getContractAmount());//合同金额小写
        dataItem.put("m4p4_contamtcap",contract.getContractAmountCapital());//合同金额大写
//        dataItem.put("m4p4_israisefund", false); 是否使用募集资金
        dataItem.put("m4p4_sealtype", contract.getContractSealType());
        dataItem.put("org_number", contract.getContractCompanyCode());//甲方
        dataItem.put("m4p4_partyb_number", contract.getContractSupplierCode());//乙方
        dataItem.put("m4p4_currency_number", contract.getContractCurrency());//货币编码
        dataItem.put("m4p4_applier_number", contract.getUserAccount());//申请人工号
        dataItem.put("m4p4_isterminated", 0);//是否终止 默认传0
        dataItem.put("m4p4_contract_date", contract.getSignDate()); //合同签订日期
        dataItem.put("m4p4_warranty_period1", contract.getQualityDate()); //质保期限
        dataItem.put("m4p4_early_stage", contract.getIsInitial()); //是否初期
//        dataItem.put("m4p4_applydept_number",contract.getContractDemandUserDept());//申请部门

        JSONArray entryentityArray = new JSONArray();
        List<ContractDetail> details = contractDetailService.list(new LambdaQueryWrapper<ContractDetail>()
                .eq(ContractDetail::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .eq(ContractDetail::getContractId, conId));

                List<TaxInfo> taxInfos = taxService.list();
                Map<String, BigDecimal> taxInfosMap = taxInfos.stream()
                .collect(Collectors.toMap(
                        TaxInfo::getTaxCode,
                        TaxInfo::getTaxValue
                ));
        if (CollectionUtil.isNotEmpty(details)){
            for(int i=0;i<details.size();i++){
                ContractDetail item=details.get(i);
                JSONObject entryItem = new JSONObject();
                entryItem.put("seq", item.getLineNo());//采购明细行序号
                entryItem.put("m4p4_assettype_number", item.getSubjectCode());//资产类别
                entryItem.put("m4p4_name", item.getMaterialName());//物品名称
                entryItem.put("m4p4_modelspec",item.getMaterialSpec());//型号规格
                entryItem.put("m4p4_brand",item.getMaterialBrand());//品牌
                entryItem.put("m4p4_prno", item.getPurchaseCode());//请购单编号
                entryItem.put("m4p4_qty", item.getNum());//数量
                entryItem.put("m4p4_untaxprice", item.getNoTaxPrice());//未税单价
                BigDecimal taxValue = taxInfosMap.get(item.getTaxRateCode()); //取code进行查询
                entryItem.put("m4p4_taxrate", taxValue.multiply(BigDecimal.valueOf(100)));//税率
                entryItem.put("m4p4_taxprice", item.getPrice());//含税单价
                entryItem.put("m4p4_taxamt", item.getPrice().multiply(item.getNum()));
//                entryItem.put("m4p4_assetno", "ASSET-RD-2025008")资产编号
//                entryItem.put("m4p4_assetusage", "01");资产用途
//                entryItem.put("m4p4_assetstatus", "使用中");资产情况
                entryItem.put("m4p4_unit_number", item.getBasisUnit());//单位
                entryItem.put("m4p4_keeper_number", item.getUserCode());//使用人
                entryItem.put("m4p4_prdept_number", item.getUseDeptCode());//使用部门
                entryItem.put("m4p4_costcenter_number", item.getCostCenterCode());//成本中心编码
                entryItem.put("m4p4_location_number", item.getStockPoint());//库存地点名称
                entryItem.put("m4p4_mouldpartname", item.getMaterialName());//.开模件名称
                entryItem.put("m4p4_mouldtype", item.getModelType());//模具类型
                entryItem.put("m4p4_mouldno", item.getModelNumber());//模具编号
                entryItem.put("m4p4_customer_number", item.getCustomerCode());//客户编码

                entryentityArray.add(entryItem);
            }
        }
        dataItem.put("entryentity", entryentityArray);


        List<ContractPayStage> contractPayStageList = contractPayStageService.list(new LambdaQueryWrapper<ContractPayStage>()
                .eq(ContractPayStage::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .eq(ContractPayStage::getContractId, conId));

        JSONArray payEntryArray = new JSONArray();
        if (CollectionUtil.isNotEmpty(contractPayStageList)){
            for(int j=0;j<contractPayStageList.size();j++){
                ContractPayStage item=contractPayStageList.get(j);
                JSONObject payItem = new JSONObject();
                payItem.put("seq", j+1);
                payItem.put("m4p4_paydate", item.getPaymentTime());//付款日期
                if(item.getPaymentRatio()!=null){
                    payItem.put("m4p4_payrate", item.getPaymentRatio().multiply(BigDecimal.valueOf(100)));//付款比例
                }
                payItem.put("m4p4_payamt", item.getPaymentAmount());//付款金额
                payItem.put("m4p4_remark", item.getRemark());//描述
                payItem.put("m4p4_payphase", item.getPaymentPeriod());//付款阶段
                payItem.put("m4p4_payprecondition", item.getPaymentRequirement());//付款前提条件
//                payItem.put("m4p4_payway_number", "101");//付款阶段
                switch (item.getPaymentWay()) {//付款方式
                    case "B":
                        payItem.put("m4p4_payway_number", "101");//银行转账
                        break;
                    case "C":
                        payItem.put("m4p4_payway_number", "201");//承兑汇票
                        break;
                    case "D":
                        payItem.put("m4p4_payway_number", "701");//应收对冲应付
                        break;
                    default:
                        payItem.put("m4p4_payway_number", "");
                        break;
                }
                payEntryArray.add(payItem);
            }
        }
        dataItem.put("m4p4_entryentity", payEntryArray);
        dataArray.add(dataItem);
        reqBody.put("data", dataArray);
        log.info("dataArray"+reqBody.toJSONString());
        FinancialShareApiResultDTO tenderApiResult = financialShareClient.submitContractToFinance(accessToken, reqBody);
        JSONObject data = financialShareUtil.handleApiResult(tenderApiResult, "创建合同到共享");
        JSONArray resultArray = data.getJSONArray("result");
        for (Object object : resultArray) {
            JSONObject jsonObject = (JSONObject) object;
            String processId = jsonObject.getString("id");
            JSONObject keys = jsonObject.getJSONObject("keys");
            contract.setContractState(2);
            contract.setOaProcessId(processId);
            contractService.updateById(contract);
        }
        //提交附件到共享
        try {
            submitStampFileToGx(conId, gxApplyId,"2");
        } catch (Exception e) {
            throw new DaoException("提交合同附件到共享失败");
        }
        return tenderApiResult;
    }

    @Override
    public List<String> submitStampFileToGx(String conId, String gxApplyId,String type) {
        Contract contract = contractService.getById(conId);
        String contractFiles=null;
        String contractFiles2=null;
        String attachmentKey="attachmentpanel";
        String signAttachmentKey="m4p4_attachmentpanel";
        String billNumber="m4p4_fa_contractreview";
        List<String> strings= new ArrayList<>();
        if("1".equals(type)){
            //盖章附件
            contractFiles = contract.getContractSignFiels();
            if (StringUtil.isBlank(contractFiles) ) {
                throw new DaoException("提交盖章附件不能为空");
            }
             contract.setContractSignFileStatue(ContractConst.MANUAL);
             strings = getStrings(contractFiles, contract, signAttachmentKey, billNumber);

            if(contract.getContractState().intValue()==4){
                //驳回状态重新将合同附件传共享
                contractFiles2 = contract.getContractFiles();
                List<String> strings1 = getStrings(contractFiles2, contract, attachmentKey, billNumber);
                strings.addAll(strings1);
            }
        }else{
            //合同附件
            contractFiles = contract.getContractFiles();
            if (StringUtil.isBlank(contractFiles) ) {
                throw new DaoException("提交附件不能为空");
            }
             strings = getStrings(contractFiles, contract, attachmentKey, billNumber);
        }
        contractService.updateById(contract);
        return  strings;
    }

    private List<String> getStrings(String contractFiles, Contract contract, String attachmentKey, String billNumber) {
        List<Long> ids = Arrays.stream(contractFiles.split(",")) // 按逗号分割字符串
                .map(String::trim) // 去除首尾空格（防止有多余空格）
                .filter(s -> !s.isEmpty()) // 过滤空字符串（避免分割后出现空值）
                .map(Long::valueOf) // 转换为Long类型
                .collect(Collectors.toList());

        List<String> strings = financialShareUtil.uploadBatchFileForBill(ids, contract.getContractCode(), attachmentKey, billNumber);
        return strings;
    }

    @Override
    public List<ContractPrintDTO> getPrintData(String contractId) {
        Contract contract = contractService.getById(contractId);
        ContractPrintDTO contractPrintDTO = contractConvert.enToPrintDto(contract);
        //付款方式
        final DictDTO paymentWay = dictClient.getDictByTypeAndCode(DictCode.PAYMENT_WAY.getCode(),
                contractPrintDTO.getContractPaymentWay());
        if (Objects.nonNull(paymentWay)) {
            contractPrintDTO.setContractPaymentWay(paymentWay.getName());
        }
        //创建人
        if (contract.getCreateUser() != null) {
            final UserDTO spUser = userClient.getByUserId(contract.getCreateUser());
            if (Objects.nonNull(spUser)) {
                contractPrintDTO.setCreateName(spUser.getUsername());
            }
        }
        final Map<String, String> dictCache = dictClient.getDicMapByType(CONTRACT_MRO_SUBJECT.getCode());
        List<ContractDetail> details = contractDetailService.list(new LambdaQueryWrapper<ContractDetail>()
                .eq(ContractDetail::getDeleteFlag,DelFlag.NORMAL.getStatus())
                .eq(ContractDetail::getContractId, contractId));
        if (CollectionUtil.isNotEmpty(details)){
            details.forEach(contractDetail -> {
                final String s = dictCache.get(contractDetail.getSubjectCode());
                contractDetail.setSubjectCode(s);
                contractDetail.setAmount(contractDetail.getNum().multiply(contractDetail.getPrice()));
                contractDetail.setLineNo(contractDetail.getLineNo()+1);
            });
            contractPrintDTO.setTaxRateName(details.get(0).getTaxRateName());
        }
        List<ContractItemPrintDTO>  iemDto=contractConvert.entitieToPrintDTOList(details);
        if (CollectionUtil.isNotEmpty(iemDto)){
            iemDto.forEach(contractDetail -> {
                if(contractDetail.getDeliveryDate()!=null){
                    String dateOnly = contractDetail.getDeliveryDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    contractDetail.setDeliveryDate1(dateOnly);
                }
            });
            contractPrintDTO.setTaxRateName(details.get(0).getTaxRateName());
        }
        contractPrintDTO.setDetailList(iemDto);

        //name 审核人

        return Lists.newArrayList(contractPrintDTO);
    }

    @Override
    public List<Map<String, String>> detailMroImport(MultipartFile file) {
        try {
            List<Map<String,String>> dataList = EasyExcelImportUtils.parseExcelToData(file.getInputStream(), 2);
            //税率
            final List<TaxDTO> taxDTOS = taxClient.getAll();
            final Map<String, TaxDTO> taxCache = taxDTOS.stream().collect(Collectors.toMap(TaxDTO::getTaxName, a -> a));
            final Set<String> taxNames = taxCache.keySet();

            for (Map<String,String> map : dataList){
                if (StrUtil.isEmpty(map.get("purchaseCode"))){
                    throw new DaoException("资产申请单号必填");
                }
                if (StrUtil.isEmpty(map.get("itemCode"))){
                    throw new DaoException("资产申请行项目必填");
                }
                if (StrUtil.isEmpty(map.get("subjectCode"))){
                    throw new DaoException("请选择资产类别");
                }
                if (StrUtil.isNotEmpty(map.get("subjectCode"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(CONTRACT_MRO_SUBJECT.getCode(),map.get("subjectCode"));
                    map.put("subjectCode",dictDTO.getCode());
                }
//                if (StrUtil.isEmpty(map.get("materialName"))){
//                    throw new DaoException("物料名称必填");
//                }
//                if (StrUtil.isEmpty(map.get("materialSpec"))){
//                    throw new DaoException("型号规格/参数");
//                }

                if (StrUtil.isEmpty(map.get("num"))){
                    throw new DaoException("数量必填");
                }
                if (StrUtil.isNotEmpty(map.get("num"))){
                    try {
                        new BigDecimal(map.get("num"));
                    }catch (Exception e){
                        throw new DaoException(StrUtil.format("需求数量：{}格式不正确",map.get("num")));
                    }
                }

                if (StrUtil.isEmpty(map.get("basisUnit"))){
                    throw new DaoException("单位必填");
                }
                if (StrUtil.isNotEmpty(map.get("basisUnit"))){
                    DictDTO dictDTO = dictClient.getDictByTypeAndName(DictCode.UNIT.getCode(),map.get("basisUnit"));
                    map.put("basisUnit",dictDTO.getCode());
                }
                if (StrUtil.isEmpty(map.get("price"))){
                    throw new DaoException("单价(含税)必填");
                }
                if (StrUtil.isNotEmpty(map.get("price"))){
                    try {
                        new BigDecimal(map.get("price"));
                    }catch (Exception e){
                        throw new DaoException(StrUtil.format("单价(含税)：{}格式不正确",map.get("price")));
                    }
                }

                if (StrUtil.isNotEmpty(map.get("taxRateCode"))){
                    if (!taxNames.contains(map.get("taxRateCode"))) {
                        throw new DaoException(StrUtil.format("税码：{}在系统中不存在",map.get("taxRateCode")));
                    }
                    TaxDTO taxDTO = taxCache.get(map.get("taxRateCode"));
                    map.put("taxRateName",taxDTO.getTaxName());
                    map.put("taxRateCode",taxDTO.getTaxCode());
                }


                if (StrUtil.isNotEmpty(map.get("purchaseCode"))&&StrUtil.isNotEmpty(map.get("itemCode"))){
                    PurchaseApplyBillDetailClientDTO purchaseApplyBillDetailClientDTO = purchaseApplyBillDetailClient.getByBillCodeAndItemCode(map.get("purchaseCode"),map.get("itemCode"));
                    if (ObjectUtil.isNull(purchaseApplyBillDetailClientDTO)){
                        throw new DaoException(StrUtil.format("请购单编码：{}在系统中不存在",map.get("purchaseCode")));
                    }
                    PurchaseApplyBillClientDTO purchaseApplyBill = purchaseApplyBillClient.getPurchaseApplyBill(map.get("purchaseCode"));
                    map.put("itemCode",purchaseApplyBillDetailClientDTO.getItemCode());
                    map.put("materialName",StrUtil.isEmpty(map.get("materialName"))?purchaseApplyBillDetailClientDTO.getMaterialName():map.get("materialName"));
                    map.put("materialSpec",StrUtil.isEmpty(map.get("materialSpec"))?purchaseApplyBillDetailClientDTO.getMaterialSpec():map.get("materialSpec"));
                    map.put("brand",StrUtil.isEmpty(map.get("brand"))?purchaseApplyBillDetailClientDTO.getBrand():map.get("brand"));

                    map.put("useDeptName",StrUtil.isEmpty(map.get("useDeptName"))?purchaseApplyBillDetailClientDTO.getUseDeptName():map.get("useDeptName"));
                    map.put("useDeptCode",StrUtil.isEmpty(map.get("useDeptCode"))?purchaseApplyBillDetailClientDTO.getUseDeptCode():map.get("useDeptCode"));
                    map.put("userName",StrUtil.isEmpty(map.get("userName"))?purchaseApplyBillDetailClientDTO.getUserName():map.get("userName"));
                    map.put("userCode",StrUtil.isEmpty(map.get("userCode"))?purchaseApplyBillDetailClientDTO.getUserCode():map.get("userCode"));
                    map.put("costCenterCode",StrUtil.isEmpty(map.get("costCenterCode"))?purchaseApplyBillDetailClientDTO.getCostCenterCode():map.get("costCenterCode"));
                    map.put("costCenterName",StrUtil.isEmpty(map.get("costCenterName"))?purchaseApplyBillDetailClientDTO.getCostCenterName():map.get("costCenterName"));
                    if (StrUtil.isEmpty(map.get("customerCode"))){
                        map.put("customerCode",purchaseApplyBillDetailClientDTO.getCustomerCode());
                        map.put("customerName",purchaseApplyBillDetailClientDTO.getCustomerName());
                    }
                    map.put("stockPoint",StrUtil.isEmpty(map.get("stockPoint"))?purchaseApplyBill.getStockPoint():map.get("stockPoint"));
//                    map.put("mainUses",StrUtil.isEmpty(map.get("mainUses"))?purchaseApplyBill.getMainUses():map.get("mainUses"));
                    map.put("applyProjectType",StrUtil.isEmpty(map.get("applyProjectType"))?purchaseApplyBill.getApplyProjectType():map.get("applyProjectType"));
                    map.put("modelApply",StrUtil.isEmpty(map.get("modelApply"))?purchaseApplyBill.getModelApply():map.get("modelApply"));
                    map.put("projectProcess",StrUtil.isEmpty(map.get("projectProcess"))?purchaseApplyBill.getProjectProcess():map.get("projectProcess"));
                }
            }
            return dataList;
        } catch (IOException e) {
            throw new DaoException("读取Excel失败");
        }
    }

    @Override
    public List<ContractDetailDTO> selectContractDetailExportData(String queryStr) {
        if (queryStr != null && queryStr.length() >= 2
                && queryStr.startsWith("\"") && queryStr.endsWith("\"")) {
            queryStr = queryStr.substring(1, queryStr.length() - 1);
        }
        List<ContractDetail> contractDetail = contractDetailService.list(Wrappers.lambdaQuery(ContractDetail.class).eq(ContractDetail::getContractCode,queryStr));
        return contractConvert.entitieToDTOList(contractDetail);
    }

    @Override
    public void contractTerminateCheck(String contractId) {
        Contract selectedContract = contractService.getById(contractId);
        String selectedContractCode = selectedContract.getContractCode();
        // 1.第一层，合同本身
        // 终止合同重复校验
        List<Contract> selfTerminateContractList = contractService.list(new LambdaQueryWrapper<Contract>()
                .eq(Contract::getAssociationContract, selectedContractCode)
                .eq(Contract::getContractType, "08")
                .eq(Contract::getDeleteFlag, "0"));
        if (selfTerminateContractList.size() > 0) {
            String selfTerminateContractCode = selfTerminateContractList.get(0).getContractCode();
            throw new DaoException(String.format("合同【%s】已存在终止合同【%s】，请勿重复创建！", selectedContractCode, selfTerminateContractCode));
        }
        // 在途请款校验
        List<ContractPaymentApply> underPaymentList = contractPaymentApplyService.findUnderPaymentByContractCode(selectedContractCode);
        if (underPaymentList.size() > 0) {
            List<String> applyNoList = underPaymentList.stream().map(ContractPaymentApply::getApApplyNo).toList();
            String message = String.format("合同【%s】存在在途请款单【%s】，请先完结请款单！", selectedContractCode, String.join(",", applyNoList));
            throw new DaoException(message);
        }
        if ("07".equals(selectedContract.getContractType())) {
            // 2.第二层，合同类型：变更合同
            List<Contract> mainContractList = contractService.list(new LambdaQueryWrapper<Contract>()
                    .eq(Contract::getContractCode, selectedContract.getAssociationContract())
                    .eq(Contract::getDeleteFlag, "0"));
            if (mainContractList.size() > 0) {
                // 终止合同重复校验
                // 判断主合同是否有终止合同
                String mainContractCode = mainContractList.get(0).getContractCode();
                List<Contract> mainContractTerminateContractList = contractService.list(new LambdaQueryWrapper<Contract>()
                        .eq(Contract::getAssociationContract, mainContractCode)
                        .eq(Contract::getContractType, "08")
                        .eq(Contract::getDeleteFlag, "0"));
                if (mainContractTerminateContractList.size() > 0) {
                    String mainContractTerminateContractCode = mainContractTerminateContractList.get(0).getContractCode();
                    throw new DaoException(String.format("变更合同【%s】的主合同【%s】有终止合同【%s】，不允许发起终止！", selectedContractCode, mainContractCode, mainContractTerminateContractCode));
                }
                // 在途请款校验
                List<ContractPaymentApply> mainContractUnderPaymentList = contractPaymentApplyService.findUnderPaymentByContractCode(mainContractCode);
                if (mainContractUnderPaymentList.size() > 0) {
                    List<String> applyNoList = underPaymentList.stream().map(ContractPaymentApply::getApApplyNo).toList();
                    String message = String.format("变更合同【%s】的主合同【%s】存在在途请款单【%s】，请先完结请款单！", selectedContractCode, mainContractCode, String.join(",", applyNoList));
                    throw new DaoException(message);
                }
            }
        } else {
            // 3.第三层，合同类型：主合同
            // 判断是否有任意一条变更合同有【未审批通过】的终止合同
            List<Contract> changeContractList = contractService.list(new LambdaQueryWrapper<Contract>()
                    .eq(Contract::getAssociationContract, selectedContractCode)
                    .eq(Contract::getContractType, "07")
                    .eq(Contract::getDeleteFlag, "0"));
            if (changeContractList.size() > 0) {
                List<String> changeContractCodeList = changeContractList.stream().map(Contract::getContractCode).toList();
                for (String changeContractCode : changeContractCodeList) {
                    // 终止合同重复校验
                    List<Contract> changeTerminateContractList = contractService.list(new LambdaQueryWrapper<Contract>()
                            .eq(Contract::getAssociationContract, changeContractCode)
                            .eq(Contract::getContractType, "08")
                            .eq(Contract::getDeleteFlag, "0")
                            .notIn(Contract::getContractState, 3));
                    if (changeTerminateContractList.size() > 0) {
                        String changeTerminateContractCode = changeTerminateContractList.get(0).getContractCode();
                        throw new DaoException(String.format("合同【%s】存在变更合同【%s】有终止合同【%s】，不允许发起终止！", selectedContractCode, changeContractCode, changeTerminateContractCode));
                    }
                    // 在途请款校验
                    List<ContractPaymentApply> mainContractUnderPaymentList = contractPaymentApplyService.findUnderPaymentByContractCode(changeContractCode);
                    if (mainContractUnderPaymentList.size() > 0) {
                        List<String> applyNoList = underPaymentList.stream().map(ContractPaymentApply::getApApplyNo).toList();
                        String message = String.format("合同【%s】存在变更合同【%s】存在在途请款单【%s】，请先完结请款单！", selectedContractCode, changeContractCode, String.join(",", applyNoList));
                        throw new DaoException(message);
                    }
                }
            }
        }
    }

    @Override
    public String formSave(ContractMroSaveDTO saveDTO) {
        // 合同主表
        Contract contract = saveDTO.getForm();
        if (ObjectUtils.isEmpty(contract.getId())) {
            // 新增
            contract.setCreateTime(LocalDateTime.now());
            contract.setCreateUser(LoginUtil.getUserId());
            if (StringUtils.contains(contract.getDataSourcesNo(), "RFQ")){
                contract.setDataSources(3);
            }
            // 发起变更 | 发起终止 的情况，设置子合同编码
            if (StringUtils.equalsAny(contract.getContractType(), "07", "08")) {
                contract.setContractCode(contractSubSeqLogic.getRealSubContractCode(contract.getAssociationContract()));
            }
        } else {
            // 编辑
            // 检查合同编码是否存在
            long count = contractService.count(new LambdaQueryWrapper<Contract>()
                            .eq(Objects.nonNull(contract.getContractCode()),Contract::getContractCode, contract.getContractCode())
                            .notIn(Objects.nonNull(contract.getId()),Contract::getId, contract.getId()));
            if (count > 0) {
                throw new DaoException("合同编码已存在，请修改!");
            }
            contract.setUpdateTime(LocalDateTime.now());
            contract.setUpdateUser(LoginUtil.getUserId());

        }
        contractService.saveOrUpdate(contract);

        // 合同明细
        contractDetailService.update(new LambdaUpdateWrapper<ContractDetail>()
                .set(ContractDetail::getDeleteFlag, DelFlag.DELETE.getStatus())
                .eq(ContractDetail::getContractId, contract.getId())
        );
        List<ContractDetail> contractDetailList = saveDTO.getContractDetailList();
        AtomicInteger lineNoCounter = new AtomicInteger(1);
        if (CollectionUtil.isNotEmpty(contractDetailList)) {
            contractDetailList.forEach( detail -> {
                detail.setContractCode(contract.getContractCode());
                detail.setContractId(contract.getId());
                detail.setDeleteFlag(0);
                detail.setLineNo(lineNoCounter.getAndIncrement());
            });
            contractDetailService.saveOrUpdateBatch(contractDetailList);
        }
        // 合同明细- mro
        mroService.update(new LambdaUpdateWrapper<ContractDetailMro>()
                .set(ContractDetailMro::getDeleteFlag,DelFlag.DELETE.getStatus())
                .eq(ContractDetailMro::getContractId, contract.getId())
        );
        List<ContractDetailMro> contractDetailMroList = saveDTO.getContractDetailMroList();
        if (CollectionUtil.isNotEmpty(contractDetailMroList)) {
            contractDetailMroList.forEach( mroDetail -> {
                mroDetail.setContractCode(contract.getContractCode());
                mroDetail.setContractId(contract.getId());
                mroDetail.setDeleteFlag(0);
            });
            mroService.saveOrUpdateBatch(contractDetailMroList);
        }
        // 付款阶段
        contractPayStageService.update(new LambdaUpdateWrapper<ContractPayStage>()
                .set(ContractPayStage::getDeleteFlag, DelFlag.DELETE.getStatus())
                .eq(ContractPayStage::getContractId, contract.getId())
        );
        List<ContractPayStage> contractPayStageList = saveDTO.getPayStageDetailList();
        AtomicInteger stageCounter = new AtomicInteger(1);
        if (CollectionUtil.isNotEmpty(contractPayStageList)) {
            contractPayStageList.forEach( payStage -> {
                payStage.setContractCode(contract.getContractCode());
                payStage.setContractId(contract.getId());
                payStage.setDeleteFlag(0);
                payStage.setLineNo(stageCounter.getAndIncrement());
            });
            contractPayStageService.saveOrUpdateBatch(contractPayStageList);
        }
        //回写状态
        if (ContractConst.DATASOURCES_ZB.equals(contract.getDataSources())) {
            tenderClient.updateConState(contract.getDataSourcesId(), 1);
        }
        if (ContractConst.DATASOURCES_XJ.equals(contract.getDataSources())) {
            inquiryClient.updateConState(contract.getDataSourcesId(),1);
        }
        if (ContractConst.DATASOURCES_BATCH_XJ.equals(contract.getDataSources())) {
            inquiryClient.updateConStateByNos(contract.getDataSourcesNo(), contract.getContractSupplierCode(), 1);
        }
        if (StrUtil.contains(contract.getDataSourcesNo(), "RFQ")){
            inquiryClient.updateConStateByNos(contract.getDataSourcesNo(), contract.getContractSupplierCode(), 1);
        }
        // 发起终止
        if (StringUtils.equals(saveDTO.getIsTerminated(), "1")) {
            try {
                submitContractToGx(contract.getId().toString(), contract.getOaProcessId(), "1");
            } catch (DaoException e) {
                log.error("资产合同，共享发起终止异常", e);
                return "请注意！终止合同保存成功，但提交共享失败";
            }
        }
        return null;
    }


    @Override
    public PageView selectReceiptContractDetailListPage(ChoseSupplierListQuery query) {
        final Page<ContractDetail> page = PageUtil.toPage(query);
        List<ContractDetail> details = contractDetailService.selectReceiptContractDetailListPage(page,query);
        if(!CollectionUtils.isEmpty(details)){
            List<String> dataKeys = details.stream()
                    .map(d -> d.getContractCode() + "_" + d.getLineNo())
                    .distinct()
                    .collect(Collectors.toList());
            ContractOrderQuantityDTO contactOrderNumData = contractDeliveryLogic.findContactOrderNumData(dataKeys);
            Map<String, BigDecimal> onlineNumMap = contactOrderNumData.getOnlineNumMap();
            Map<String, BigDecimal> receiveNumMap = contactOrderNumData.getReceiveNumMap();
            Map<String, BigDecimal> returntMap = contactOrderNumData.getReturntMap();
            for (ContractDetail detail : details) {
                String key = detail.getContractCode()+"_"+detail.getLineNo();
                BigDecimal onlineNum  = onlineNumMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() :  onlineNumMap.get(key);
                BigDecimal receiveNum = receiveNumMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() : receiveNumMap.get(key) ;
                BigDecimal  returnNum = returntMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() : returntMap.get(key);
                //未清数量
                BigDecimal unclearNum  = detail.getNum().subtract(onlineNum).subtract(receiveNum).add(returnNum);
                //可送数量
                BigDecimal  deliverableNum  = unclearNum;
                //收货数量
                BigDecimal shipmentNum = deliverableNum ;
                detail.setOnlineNum(onlineNum);
                detail.setReceiveNum(receiveNum);
                detail.setReturnNum(returnNum);
                detail.setUnclearNum(unclearNum);
                detail.setDeliverableNum(deliverableNum);
                detail.setShipmentNum(shipmentNum);
            }
        }




       //计算数量逻辑
        //合同明细数量 -->合同采购明细中的数量
//        BigDecimal num
//        //在途数量  -->相同合同行，送货单单据类型是”送货“，送货单单据状态是”已发货“，累计送货单行送货数量
//
//        BigDecimal onlineNum;
//        //接收数量  -->相同合同行，送货单单据类型是”送货“，送货单单据状态是”已收货“或”已记账“，累计送货单行收货数量
//
//       BigDecimal receiveNum;
//        //已退数量 -->相同合同行，送货单单据类型是”退货“，送货单单据状态是”创建退货“或”确认退货“，累计送货单行退货数量
//
//       BigDecimal returnNum;
//        //未清数量 --> = 订单数量 - 在途数量 - 接收数量 + 已退数量
//
//       BigDecimal unclearNum;
//        //可送数量 --> 可送数量 = 未清数量
//
//       BigDecimal  deliverableNum;
//        //收货数量 -->  默认等于”可送数量“，不能大于可送数量
//
//        BigDecimal shipmentNum;

        return PageUtil.getPV(details, page.getTotal());
    }

    /**
     * 排序
     * @param wrapper
     * @param query
     */
    private void applySort(LambdaQueryWrapper<Contract> wrapper, ContractMangeQuery query) {
        if (StrUtil.isBlank(query.getSort())) {
            // 默认排序
            wrapper.orderByDesc(Contract::getCreateTime);
            return;
        }

        boolean asc = "asc".equalsIgnoreCase(query.getOrder());

        switch (query.getSort()) {
            case "contractCode":
                wrapper.orderBy(true, asc, Contract::getContractCode);
                break;
            case "contractState":
                wrapper.orderBy(true, asc, Contract::getContractState);
                break;
            case "contractType":
                wrapper.orderBy(true, asc, Contract::getContractType);
                break;
            case "oaCode":
                wrapper.orderBy(true, asc, Contract::getOaCode);
                break;
            case "gxTerminateContractCode":
                wrapper.orderBy(true, asc, Contract::getGxTerminateContractCode);
                break;
            case "contractSignFileStatue":
                wrapper.orderBy(true, asc, Contract::getContractSignFileStatue);
                break;
            case "dataSources":
                wrapper.orderBy(true, asc, Contract::getDataSources);
                break;
            case "dataSourcesNo":
                wrapper.orderBy(true, asc, Contract::getDataSourcesNo);
                break;
            case "contractPurchaseGroup":
                wrapper.orderBy(true, asc, Contract::getContractPurchaseGroup);
                break;
            case "contractSupplierCode":
                wrapper.orderBy(true, asc, Contract::getContractSupplierCode);
                break;
            case "createTime":
                wrapper.orderBy(true, asc, Contract::getCreateTime);
                break;
            case "updateTime":
                wrapper.orderBy(true, asc, Contract::getUpdateTime);
                break;
            default:
                // 非法字段，兜底
                wrapper.orderByDesc(Contract::getCreateTime);
        }
    }

    @Override
    public List<ContractDetail> selectReceiptContractDetailList(ChoseSupplierListQuery query) {
    //查询合同信息不需要分页
        List<ContractDetail> details =  contractDetailService.selectReceiptContractDetailList(query);
        if(!CollectionUtils.isEmpty(details)){
        //进行金额计算，将不符合的数据进行导入页面提示
            List<String> dataKeys = details.stream()
                    .map(d -> d.getContractCode() + "_" + d.getLineNo())
                    .distinct()
                    .collect(Collectors.toList());
            ContractOrderQuantityDTO contactOrderNumData = contractDeliveryLogic.findContactOrderNumData(dataKeys);
            Map<String, BigDecimal> onlineNumMap = contactOrderNumData.getOnlineNumMap();
            Map<String, BigDecimal> receiveNumMap = contactOrderNumData.getReceiveNumMap();
            Map<String, BigDecimal> returntMap = contactOrderNumData.getReturntMap();
            for (ContractDetail detail : details) {
                //收货数量大于未清数量就要给出错误提示
                String key = detail.getContractCode()+"_"+detail.getLineNo();
                BigDecimal onlineNum  = onlineNumMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() :  onlineNumMap.get(key);
                BigDecimal receiveNum = receiveNumMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() : receiveNumMap.get(key) ;
                BigDecimal  returnNum = returntMap.get(key) == null ? BigDecimal.ZERO.stripTrailingZeros() : returntMap.get(key);
                //未清数量
                BigDecimal unclearNum  = detail.getNum().subtract(onlineNum).subtract(receiveNum).add(returnNum);
                //可送数量
                BigDecimal  deliverableNum  = unclearNum;
                //收货数量
                BigDecimal shipmentNum = deliverableNum ;
                detail.setOnlineNum(onlineNum);
                detail.setReceiveNum(receiveNum);
                detail.setReturnNum(returnNum);
                detail.setUnclearNum(unclearNum);
                detail.setDeliverableNum(deliverableNum);
                detail.setShipmentNum(shipmentNum);
            }

        }
        return details;
    }
}
