package com.jwipc.finance.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.api.dto.ErpApiResult;
import com.jwipc.api.dto.ErpApiResult1;
import com.jwipc.api.dto.OaFileParamDTO;
import com.jwipc.constant.DictCode;
import com.jwipc.dto.ExportDataDTO;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.constant.PaymentOaClient;
import com.jwipc.finance.convert.PaymentAdvanceApplyConvert;
import com.jwipc.finance.dto.*;
import com.jwipc.finance.entity.*;
import com.jwipc.finance.logic.PaymentAdvanceApplyDetailLogic;
import com.jwipc.finance.logic.PaymentAdvanceApplyLogic;
import com.jwipc.finance.logic.PaymentAdvanceRefundTransferApplyDetailLogic;
import com.jwipc.finance.logic.PaymentPlanLogic;
import com.jwipc.finance.model.po.*;
import com.jwipc.finance.model.query.PaymentApplyHeadQuery;
import com.jwipc.finance.model.query.PaymentApplyItemQuery;
import com.jwipc.finance.service.*;
import com.jwipc.order.clent.dto.PurchaseDetailDTO;
import com.jwipc.order.clent.dto.PurchaseOrderDTO;
import com.jwipc.order.client.PurchaseOrderClient;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.clent.dto.SupplierBankDTO;
import com.jwipc.supplier.clent.dto.SupplierContactsDTO;
import com.jwipc.supplier.clent.dto.SupplierDTO;
import com.jwipc.supplier.client.SupplierClient;
import com.jwipc.sys.client.*;
import com.jwipc.sys.client.dto.*;
import com.jwipc.sys.dto.BusinessAttachmentDTO;
import com.jwipc.sys.dto.KingdeeInvoiceCloudImageDTO;
import com.jwipc.sys.entity.Attachment;
import com.jwipc.sys.entity.BusinessAttachment;
import com.jwipc.sys.logic.BusinessAttachmentLogic;
import com.jwipc.sys.logic.KingdeeImageLogic;
import com.jwipc.sys.service.IAttachmentService;
import com.jwipc.sys.service.IBusinessAttachmentService;
import com.jwipc.sys.util.FinancialShareUtil;
import com.jwipc.util.DateUtils;
import com.jwipc.util.EasyExcelUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * </p>
 *
 * @author wt
 * @version 1.0
 * @since 2024/3/8
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PaymentAdvanceApplyLogicImpl implements PaymentAdvanceApplyLogic {

    private final IPaymentAdvanceApplyService paymentAdvanceApplyService;
    private final IAttachmentService attachmentService;
    private final KingdeeImageLogic kingdeeImageLogic;
//    private final IPaymentAdvanceApplyAttachmentService paymentAdvanceApplyAttachmentService;
    private final IBusinessAttachmentService businessAttachmentService;
    private final BusinessAttachmentLogic businessAttachmentLogic;
    private final PaymentAdvanceApplyConvert paymentAdvanceApplyConvert;
    private final SequenceClient sequenceClient;
    private final FactoryClient factoryClient;
    private final DictClient dictClient;
    private final TaxClient taxClient;
    private final SupplierClient supplierClient;
    private final EmailSendClient emailSendClient;
    private final UserClient userClient;
    private final IPaymentAdvanceApplyDetailService paaDetailService;
    private final FileClient fileClient;
    private final PurchaseOrderClient purchaseOrderClient;
    private final CompanyClient companyClient;
    private final PaymentOaClient paymentOaClient;
    private final PaymentAdvanceApplyDetailLogic paymentAdvanceApplyDetailLogic;
    private final PaymentAdvanceRefundTransferApplyDetailLogic paymentAdvanceRefundTransferApplyDetailLogic;
    private final PaymentPlanLogic paymentPlanLogic;
    private final IReceiveVoucherService receiveVoucherService;
    private final IInvoicedApplyService invoicedApplyService;
    private final static String PaymentAdvanceLock = "PaymentAdvanceLock_";
    private final StringRedisTemplate redisTemplate;
    private final FinancialShareUtil financialShareUtil;
    private final IFinPaymentConfirmLogService finPaymentConfirmLogService;

    @Override
    public PageView selectListByPage(PaymentApplyHeadQuery query) {
        final Page<PaymentAdvanceApply> dbPage = PageUtil.toPage(query);
        List<PaymentAdvanceApply> poList = paymentAdvanceApplyService.selectListByPage(dbPage, query);

        List<PaymentAdvanceApplyBaseDTO> dtoList = paymentAdvanceApplyConvert.POToDTOList(poList);
        return PageUtil.getPV(dtoList, dbPage.getTotal());
    }

    @Override
    public PaymentAdvanceApplyListDTO selectById(Long id) {
        PaymentAdvanceApplyPO advanceApply = paymentAdvanceApplyService.selectById(id);

        return paymentAdvanceApplyConvert.poToDto(advanceApply);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dataSave(PaymentAdvanceApplySaveDto data) throws Exception {
        List<PaymentAdvanceApplyDetail> pcaDetailList = Lists.newArrayList();
        for (PaymentAdvanceApplySaveDto.ApplyDetail ad : data.getItemList()) {
            pcaDetailList.add(paymentAdvanceApplyConvert.dtoToEntityDetail(ad.toPaaDetail()));
        }

        BigDecimal totalBudOutMoney = BigDecimal.ZERO;
        BigDecimal totalDiscountMoney = BigDecimal.ZERO;
        for (PaymentAdvanceApplyDetail detail : pcaDetailList) {
            totalBudOutMoney = totalBudOutMoney.add(detail.getBudOutMoney() != null ? detail.getBudOutMoney() : BigDecimal.ZERO);
            totalDiscountMoney = totalDiscountMoney.add(detail.getDiscountMoney() != null ? detail.getDiscountMoney() : BigDecimal.ZERO);
        }
        paymentAdvanceApplyService.checkAmount(pcaDetailList, data.getDelItemIdList());
        Long id = (1 == data.getSaveType()) ? IdWorker.getId() : data.getId();
        if (1 == data.getSaveType()) {
//            String orderCode = sequenceClient.createSequenceNo("payment_advance_apply");
            String orderCode = sequenceClient.getCodeSequenceNo("payment_advance_apply", 4);
            data.setApApplyNo(orderCode);
            PaymentAdvanceApply headData = paymentAdvanceApplyConvert.dtoToEntity(data.toPaa());
            headData.setId(id);
            headData.setCreateTime(LocalDateTime.now());
            headData.setCreateUserId(LoginUtil.getUserId());
            headData.setCreateUserCode(LoginUtil.getAccount());
            headData.setCreateUserName(LoginUtil.getName());
            headData.setUpdateUserId(LoginUtil.getUserId());
            headData.setActualityPayMoney(totalBudOutMoney.subtract(totalDiscountMoney));
            headData.setOaBorrowMoney(totalBudOutMoney);
            headData.setStatus(1);
            final String result = paymentAdvanceApplyService.createAdvanceApply(headData, pcaDetailList, data.getIsPushOa(), data.getAdviceFjid());
            if (StringUtils.isNotEmpty(result)) {
                throw new DaoException("数据保存成功。但" + result);
            }
            if (CollectionUtils.isNotEmpty(data.getLogDetailList())) {
                setConfirmLog(data.getLogDetailList(), headData.getId(), headData.getApApplyNo());
            }
        }

        if (2 == data.getSaveType()) {
            PaymentAdvanceApply headData = paymentAdvanceApplyConvert.dtoToEntity(data.toPaa());
            headData.setUpdateTime(LocalDateTime.now());
            headData.setUpdateUserId(LoginUtil.getUserId());
            headData.setUpdateUserCode(LoginUtil.getAccount());
            headData.setUpdateUserName(LoginUtil.getName());
//            headData.setStatus(1);
            headData.setActualityPayMoney(totalBudOutMoney.subtract(totalDiscountMoney));
            headData.setOaBorrowMoney(totalBudOutMoney);
            final String result = paymentAdvanceApplyService.editAdvanceApply(headData, pcaDetailList, data.getDelItemIdList(), data.getIsPushOa(), data.getAdviceFjid());
            if (StringUtils.isNotEmpty(result)) {
                throw new DaoException("数据保存成功。但" + result);
            }
            if (CollectionUtils.isNotEmpty(data.getLogDetailList())) {
                setConfirmLog(data.getLogDetailList(), headData.getId(), headData.getApApplyNo());
            }
        }

        // 附件关系
        businessAttachmentService.remove(Wrappers.lambdaQuery(BusinessAttachment.class).eq(BusinessAttachment::getBusinessId,id));
        List<BusinessAttachmentDTO> businessAttachmentDTOList = data.getBusinessAttachmentDTOList();
        businessAttachmentDTOList.forEach(item -> {
            item.setId(null);
            item.setBusinessId(id);
            item.setDeleteFlag(0);
            item.setBusinessTypeCode("payment_advance_apply");
        });
        businessAttachmentLogic.saveAttachment(businessAttachmentDTOList);

        this.deleteImg(id);
        this.deletePoImg(id);

        this.toImg(String.valueOf(id));
        this.toPoImg(id);
    }
    @Override
    public List<String> saveCheck(PaymentAdvanceApplySaveDto data){
        List<String> resultList = new ArrayList<>();
        LambdaQueryWrapper<PaymentAdvanceApply> wrapper = new LambdaQueryWrapper<PaymentAdvanceApply>()
                .eq(PaymentAdvanceApply::getPaymentCompanyName, data.getPaymentCompanyName())
                .eq(PaymentAdvanceApply::getSupBankName, data.getSupBankName())
                .eq(PaymentAdvanceApply::getSupBankAccount, data.getSupBankAccount())
                .eq(PaymentAdvanceApply::getSupBankCode, data.getSupBankCode())
                .eq(PaymentAdvanceApply::getBankInterCode, data.getBankInterCode())
                .eq(PaymentAdvanceApply::getBankAddress, data.getBankAddress());
//        if (ObjectUtil.isNotNull(data.getId())){
//            wrapper.ne(PaymentAdvanceApply::getId, data.getId());
//        }
        wrapper.last(" limit 1");
        PaymentAdvanceApply bank = paymentAdvanceApplyService.getOne(wrapper);
        if (ObjectUtil.isNull( bank)&&ObjectUtil.isNull(data.getId())){
//            return StrUtil.format("供应商：{}、银行名称：{}、银行账号：{}、银行代码：{}、银行国际代码：{}、银行地址：{}为第一次付款，请核对银行信息", data.getSupplierName(), data.getPaymentCompanyName(), data.getSupBankName(), data.getSupBankAccount(), data.getSupBankCode(), data.getBankInterCode(), data.getBankAddress());
            resultList.add(StrUtil.format("此供应商的银行信息为第一次付款，请核对银行信息"));
        }
        for (PaymentAdvanceApplySaveDto.ApplyDetail ad : data.getItemList()) {
            //预付请款，相同供应商、相同订单、相同请款金额，弹窗提醒请款人：
            List<PaymentAdvanceApplyDetail> list2 = paymentAdvanceApplyService.findDataBySupplierAndPoCodeAndAmount(data.getSupplierCode(), ad.getPoCode(), ad.getBudOutMoney(),data.getId());
            if (CollectionUtils.isNotEmpty(list2)){
                resultList.add(StrUtil.format("供应商：{}、采购订单：{}、本次申请金额：{}存在重复申请的数据，单号：{}", data.getSupplierName(), ad.getPoCode(), ad.getBudOutMoney(),list2.get(0).getAppNo()));
            }
        }
        // 防多付
        // 逾期款项与本月到期款项与本次支付金额的逻辑校验
        BigDecimal applyPaymentAmount = data.getOaBorrowMoney();        // 本次支付金额
        BigDecimal overdueAmount = data.getOverdueAmount();             // 逾期款项
        BigDecimal dueAmount = data.getDueAmount();                     // 本月到期款项
        BigDecimal unClearedAmount;                                     // 未清账预付款
        // 未清账预付款 = ①+②-③+④
        //①相同供应商预付款申请单状态是付款成功，且未转单，行未删除，累计行未抵扣金额，行未抵扣金额=行本次申请金额-行已冲账金额；
        BigDecimal unCleared1 = paymentAdvanceApplyService.getUnCleared1(data.getSupplierCode());
        //②相同供应商预付款申请单状态是止付，累计单头已付款金额；
        BigDecimal unCleared2 = paymentAdvanceApplyService.getUnCleared2(data.getSupplierCode());
        //③预付款退款金额：相同供应商，预付款变更单类型是退款，状态是已发布，行未删除，累计行的本次登记含税金额；
        BigDecimal unCleared3 = paymentAdvanceApplyService.getUnCleared3(data.getSupplierCode());
        //④预付款转单未抵扣金额：相同供应商，预付款变更单类型是转单，状态是已发布，行未删除，累计行未抵扣金额，行未抵扣金额=行的本次登记含税金额-行的已冲账含税金额；
        BigDecimal unCleared4 = paymentAdvanceApplyService.getUnCleared4(data.getSupplierCode());
        unClearedAmount = unCleared1.add(unCleared2).subtract(unCleared3).add(unCleared4);
        // 相同供应商，排除付款申请单（包括预付请款和对账请款）状态是“付款成功”、“共享审批作废”、“删除”、“止付”的付款申请单，累计行本次请款金额；
        BigDecimal inPaymentAmount = paymentAdvanceApplyService.getInPaymentAmount(data.getSupplierCode(),data.getCompanyCode()); // 在途请款单付款金额

        // 本次支付金额（付款申请单汇总金额）大于 逾期款项+本月到期款项-未清账预付款 - 在途请款单付款金额（已申请待支付，排除状态“付款完成”、“共享审批作废”、“删除”）
        if (applyPaymentAmount.compareTo(overdueAmount.add(dueAmount).subtract(unClearedAmount).subtract(inPaymentAmount)) > 0) {
            resultList.add(StrUtil.format("本次支付金额({})大于逾期款项({}) + 本月到期款项({}) - 未清账预付款({}) - 在途请款单付款金额({})",
                    applyPaymentAmount.setScale(2, RoundingMode.HALF_UP),
                    overdueAmount.setScale(2, RoundingMode.HALF_UP),
                    dueAmount.setScale(2, RoundingMode.HALF_UP),
                    unClearedAmount.setScale(2, RoundingMode.HALF_UP),
                    inPaymentAmount.setScale(2, RoundingMode.HALF_UP)));
        }
        BigDecimal accountsPayableBalance = data.getAccountsPayableBalance();   // 应付账款余额
        BigDecimal provisionalBalance = data.getProvisionalBalance();           // 应付暂估余额
        // 本次付款金额（付款申请单汇总金额） 大于  应付账款余额（已包含未清账预付款）+应付暂估余额 - 在途请款单付款金额（已申请待支付，排除状态“付款完成”、“共享审批作废”、“删除”）
        if (applyPaymentAmount.compareTo(accountsPayableBalance.add(provisionalBalance).subtract(inPaymentAmount)) > 0) {
            resultList.add(StrUtil.format("本次付款金额({})大于应付账款余额({}) + 应付暂估余额({}) - 在途请款单付款金额({})",
                    applyPaymentAmount.setScale(2, RoundingMode.HALF_UP),
                    accountsPayableBalance.setScale(2, RoundingMode.HALF_UP),
                    provisionalBalance.setScale(2, RoundingMode.HALF_UP),
                    inPaymentAmount.setScale(2, RoundingMode.HALF_UP)));
        }


        return resultList;
    }


    @Override
    public void toImg(String id) {
        PaymentAdvanceApply paymentCodApply = paymentAdvanceApplyService.getById(id);
        List<String> fileList = new ArrayList<>();
        if (StringUtils.isNotEmpty(paymentCodApply.getFiles())){
            fileList.addAll(Arrays.asList(paymentCodApply.getFiles().split(",")));
        }
        if (StringUtils.isNotEmpty(paymentCodApply.getPaymentFiles())){
            fileList.addAll(Arrays.asList(paymentCodApply.getPaymentFiles().split(",")));
        }
        if (CollUtil.isNotEmpty(fileList)) {
            List<FileResposeCDTO> fileResposeCDTOList = fileClient.getFileInfos(fileList);
            if (CollUtil.isNotEmpty(fileResposeCDTOList)) {
                KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
                kingdeeInvoiceCloudImageDTO.setImageCode(StrUtil.isNotEmpty(paymentCodApply.getImgCode())?paymentCodApply.getImgCode():sequenceClient.createSequenceNo("image_code"));
                if (CollUtil.isNotEmpty(fileResposeCDTOList)) {
                    List<BusinessAttachmentDTO> businessAttachmentList = new ArrayList<>();
                    fileResposeCDTOList.forEach(file -> {
                        BusinessAttachmentDTO businessAttachmentDTO = new BusinessAttachmentDTO();
                        businessAttachmentDTO.setFileId(file.getId());
                        businessAttachmentDTO.setImageFileId(file.getImageFileId());
                        businessAttachmentDTO.setType("payment_advance_apply");
                        businessAttachmentDTO.setFileName(file.getFileName());
                        businessAttachmentList.add(businessAttachmentDTO);
                    });
                    kingdeeInvoiceCloudImageDTO.setBusinessAttachmentList(businessAttachmentList);
                    KingdeeInvoiceCloudImageDTO result = kingdeeImageLogic.pushImage(kingdeeInvoiceCloudImageDTO);
                    //更新影像
                    fileResposeCDTOList.forEach(accountStatementAttachment -> {
                        result.getBusinessAttachmentList().forEach(businessAttachmentDTO -> {
                            if (businessAttachmentDTO.getFileId().equals(accountStatementAttachment.getId())) {
                                attachmentService.update(new LambdaUpdateWrapper<Attachment>()
                                        .set(Attachment::getImageCode, result.getImageCode())
                                        .set(Attachment::getImagePath, result.getImagePath())
                                        .set(Attachment::getImageFileId, businessAttachmentDTO.getImageFileId())
                                        .eq(Attachment::getId, accountStatementAttachment.getId()));
                            }
                        });
                    });
                    paymentAdvanceApplyService.update(new LambdaUpdateWrapper<PaymentAdvanceApply>()
                            .set(PaymentAdvanceApply::getImgCode, result.getImageCode())
                            .set(PaymentAdvanceApply::getImgTime, LocalDateTime.now())
                            .set(PaymentAdvanceApply::getImgUserId, LoginUtil.getUserId())
                            .eq(PaymentAdvanceApply::getId, id));
                }
            }
        }
    }

    /**
     * 影像化
     *
     * @param appId 预付款申请ID
     */
    @Override
    public void toPoImg(Long appId) {
        PaymentAdvanceApply paymentAdvanceApply = paymentAdvanceApplyService.getById(appId);
        //影像化
        List<BusinessAttachmentDTO> accountStatementAttachments = businessAttachmentLogic.getListByBusinessId(appId);
        if (CollUtil.isNotEmpty(accountStatementAttachments)){
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(StrUtil.isNotEmpty(paymentAdvanceApply.getPoImgCode())?paymentAdvanceApply.getPoImgCode():sequenceClient.createSequenceNo("image_code"));
            if (CollUtil.isNotEmpty(accountStatementAttachments)){
                kingdeeInvoiceCloudImageDTO.setBusinessAttachmentList(accountStatementAttachments);
                KingdeeInvoiceCloudImageDTO result = kingdeeImageLogic.pushImage(kingdeeInvoiceCloudImageDTO);
                paymentAdvanceApplyService.update(new LambdaUpdateWrapper<PaymentAdvanceApply>()
                        .set(PaymentAdvanceApply::getPoImgCode,result.getImageCode())
                        .set(PaymentAdvanceApply::getPoImgTime,LocalDateTime.now())
                        .set(PaymentAdvanceApply::getPoImgUserId,LoginUtil.getUserId())
                        .eq(PaymentAdvanceApply::getId,appId));
            }

        }
    }

    /**
     * 删除影像化
     *
     * @param appId 预付款申请ID
     */
    @Override
    public void deleteImg(Long appId) {
        //删除影像化
        PaymentAdvanceApply paymentCodApply = paymentAdvanceApplyService.getById(appId);
        if (ObjectUtil.isNull(paymentCodApply.getImgTime())){
            return;
        }
        if (StringUtils.isNotEmpty(paymentCodApply.getImgCode())&&paymentCodApply.getImgTime()!=null) {
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(paymentCodApply.getImgCode());
            kingdeeImageLogic.deleteAllImage(kingdeeInvoiceCloudImageDTO);
            paymentAdvanceApplyService.update(new LambdaUpdateWrapper<PaymentAdvanceApply>()
//                        .set(InvoicedApply::getImgCode,null)
                    .set(PaymentAdvanceApply::getImgTime,null)
                    .set(PaymentAdvanceApply::getImgUserId,null)
                    .eq(PaymentAdvanceApply::getId,appId));
        }

    }

    @Override
    public void deletePoImg(Long appId) {
        //删除影像化
        PaymentAdvanceApply paymentCodApply = paymentAdvanceApplyService.getById(appId);
        if (StringUtils.isNotEmpty(paymentCodApply.getPoImgCode())&&paymentCodApply.getPoImgTime()!=null) {
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(paymentCodApply.getPoImgCode());
            kingdeeImageLogic.deleteAllImage(kingdeeInvoiceCloudImageDTO);
            paymentAdvanceApplyService.update(new LambdaUpdateWrapper<PaymentAdvanceApply>()
//                        .set(InvoicedApply::getPoImgCode,null)
                    .set(PaymentAdvanceApply::getPoImgTime,null)
                    .set(PaymentAdvanceApply::getPoImgUserId,null)
                    .eq(PaymentAdvanceApply::getId,appId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delAdvanceApply(List<Long> applyIdList) {
        final List<PaymentAdvanceApply> paaList = paymentAdvanceApplyService.findDataStatusByIdList(applyIdList);
        String paaCode = "";
        for (PaymentAdvanceApply paa : paaList) {
            if (5 == paa.getStatus()||3 == paa.getStatus()||7 == paa.getStatus()||8 == paa.getStatus()||9 == paa.getStatus()||10 == paa.getStatus()) {
                paaCode = paa.getApApplyNo();
                break;
            }
        }

        if (StringUtils.isNotEmpty(paaCode)) {
            throw new DaoException("预付款申请单: " + paaCode + ", 当前状态不可删除, 请检查");
        }

        List<PaymentAdvanceApply> applyList = Lists.newArrayList();
        for (Long applyId : applyIdList) {
            PaymentAdvanceApply apply = new PaymentAdvanceApply();
            apply.setId(applyId);
            apply.setDeleteFlag(1);
            apply.setUpdateTime(LocalDateTime.now());
            apply.setUpdateUserId(LoginUtil.getUserId());
            apply.setUpdateUserCode(LoginUtil.getAccount());
            apply.setUpdateUserName(LoginUtil.getName());
            applyList.add(apply);

            PaymentAdvanceApply old = paymentAdvanceApplyService.getById(applyId);
            PayApplyDeleteDTO payImportToOpenDTO = new PayApplyDeleteDTO();
            payImportToOpenDTO.setBillno(old.getApApplyNo());
            if (StrUtil.isEmpty(old.getOaProcessCode())){
                continue;
            }
            //提交到共享
            String accessToken = financialShareUtil.getShareAccessToken();
            ErpApiResult1<PayImportToOpenResultDTO> result = paymentOaClient.payApplyDelete(accessToken,payImportToOpenDTO);
            if (!result.getStatus()) {
                throw new DaoException("共享系统接口报错：" + result.getMessage());
            }
        }

        if (!paymentAdvanceApplyService.updateBatchById(applyList)) {
            throw new DaoException("删除预付款申请单失败, 请联系管理员");
        }
        // 删除对账付款申请明细数据
        paaDetailService.delDetailByApplyId(applyIdList);
        //付款申请删除时，需要同时更新付款计划汇总数据 邓京术 2025-08-13
        for (PaymentAdvanceApply paa : paaList) {
            PaymentAdvanceApply advanceApply = paymentAdvanceApplyService.getById(paa.getId());
            paymentAdvanceApplyService.initPaymentPlanSummary(advanceApply, false);
        }
    }


    @Override
    public void approvalPass(String ids) {
        List<String> idList = Lists.newArrayList(ids.split(","));
        for (String s : idList) {
            PaymentAdvanceApply paymentAdvanceApply = new PaymentAdvanceApply();
            paymentAdvanceApply.setStatus(5);
            paymentAdvanceApply.setId(Long.parseLong(s));
            paymentAdvanceApplyService.updateById(paymentAdvanceApply);
        }
    }

    @Override
    public List<CreatePcaDetailPO> findByQuery(PaymentApplyItemQuery query) {
        return paymentAdvanceApplyService.findByQuery(query);
    }

    /**
     * 提交OA
     *
     * @param applyId 预付款id
     */
    @Override
    public void pushOa(String applyId) {
        //付款条件
        List<DictDTO> paymentMethods = dictClient.getDicByType(DictCode.PAYMENT_TERMS.getCode());
        final Map<String, DictDTO> paymentMethodCache = paymentMethods.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
        PaymentAdvanceApply paymentAdvanceApply = paymentAdvanceApplyService.getById(applyId);
        SupplierPayImportDTO supplierPayImportDTO = new SupplierPayImportDTO();
        //插入头
        SupplierPayImportDTO.Head head = new SupplierPayImportDTO.Head();
        //SRM业务类型
        head.setFd_srmType("16");
        //申请人工号  取付款单的申请人工号
//        head.setFd_shenQingRenXingMing(LoginUtil.getAccount());
        head.setFd_shenQingRenXingMing(paymentAdvanceApply.getCreateUserCode());
        head.setProcessId(StringUtils.isNotEmpty(paymentAdvanceApply.getOaProcessCode()) ? paymentAdvanceApply.getOaProcessCode() : "");
        //SRM单号
        head.setFd_shenQingDanHao(paymentAdvanceApply.getApApplyNo());
        //抄送人员工号（经办人）
        head.setFd_jingBanRen(StringUtils.isNotEmpty(paymentAdvanceApply.getOaHandlerCode()) ? paymentAdvanceApply.getOaHandlerCode() : paymentAdvanceApply.getCreateUserCode());
        if (StringUtils.isNotEmpty(paymentAdvanceApply.getPaymentWayCode())) {
            DictDTO dict = dictClient.getDictByTypeAndCode(DictCode.PAYMENT_WAY.getCode(), paymentAdvanceApply.getPaymentWayCode());
            //付款方式
            head.setFd_fuKuanFangShi(ObjectUtil.isNotNull(dict) ? dict.getName() : "");
        } else {
            //付款方式
            head.setFd_fuKuanFangShi("");
        }

        if (null != paymentAdvanceApply.getAdvancePaymentFlag()) {
            //是否提前付款
            head.setFd_shiFuTiQianFuKuan(paymentAdvanceApply.getAdvancePaymentFlag() == 1 ? "是" : "否");
        } else {
            //是否提前付款
            head.setFd_shiFuTiQianFuKuan("");
        }

        if (StringUtils.isNotEmpty(paymentAdvanceApply.getAcceptanceMethod())) {
            DictDTO dict = dictClient.getDictByTypeAndCode(DictCode.SUPPLIER_ACCETP_DEADLINE.getCode(), paymentAdvanceApply.getAcceptanceMethod());
            //承兑期限
            head.setFd_chengDuiQiXian(ObjectUtil.isNotNull(dict) ? dict.getName() : "");
        } else {
            //承兑期限
            head.setFd_chengDuiQiXian("");
        }
        //付款类型
        head.setFd_fuKuanLeiXing("SAPPO付款");

        //备注
        head.setFd_beiZhu(paymentAdvanceApply.getApplyRemark());
        CompanyDTO companyDTO = companyClient.getByCode(paymentAdvanceApply.getCompanyCode());
        //付款公司
        head.setFd_fuKuanGongSi(companyDTO.getCompanyName());
        //付款公司编码
        head.setFd_fuKuanGongSiBianMa(paymentAdvanceApply.getCompanyCode());
        //供应商代码
        head.setFd_gongYingShangDaiMa(paymentAdvanceApply.getSupplierCode());
        //报关公司
        head.setFd_baoGuanGongSi(StrUtil.isNotEmpty(paymentAdvanceApply.getFaSupplierName()) ? paymentAdvanceApply.getFaSupplierName() : "");
        //公司代码
        head.setFd_gongSiDaiMa(paymentAdvanceApply.getCompanyCode());
        //币种
        head.setFd_biZhong(paymentAdvanceApply.getCurrencyCode());
        //币种
        head.setFd_biZhong(paymentAdvanceApply.getCurrencyCode());
        if (StringUtils.isNotEmpty(paymentAdvanceApply.getFiles())) {
            List<FileResposePreviewCDTO> fileResposePreviewDTOS = fileClient.getPreviewUrl(Arrays.asList(StringUtils.split(paymentAdvanceApply.getFiles(), ",")));
            List<OaFileParamDTO> list1 = new ArrayList<>();
            for (FileResposePreviewCDTO fileResposePreviewDTO : fileResposePreviewDTOS) {
                OaFileParamDTO build = OaFileParamDTO.builder().fileName(fileResposePreviewDTO.getFileName()).url(fileResposePreviewDTO.getPreviewUrl()).downloadUrl(fileResposePreviewDTO.getDownloadUrl()).build();
                list1.add(build);
            }
            //附件
            head.setFd_pageUrl(JSON.toJSONString(list1));
        } else {
            //附件
            head.setFd_pageUrl("");
        }
        supplierPayImportDTO.setHead(head);

        //判断供应商付款金额是否超计划付款，邓京术 2025-08-25
//        BigDecimal exceedPlanPayMonthAmount = paymentPlanLogic.findSupplierPaymentPlanSummary(paymentAdvanceApply.getSupplierCode(), paymentAdvanceApply.getCompanyCode(), 2);
//        if (exceedPlanPayMonthAmount.floatValue() > 0f) {
//            //打上超计划标识，及金额
//        }

        //插入明细
        SupplierPayImportDTO.KuanItem kuanItem = new SupplierPayImportDTO.KuanItem();
        List<SupplierPayImportDTO.KuanItem.Item> kuanItemList = new ArrayList<>();
        List<CreatePaaDetailDto> detailDtoList = paymentAdvanceApplyDetailLogic.findPaaDetailListByPaaId(Long.valueOf(applyId));
        BigDecimal fd_weiFuJinE = BigDecimal.ZERO;
        BigDecimal fd_benCiFuKuanJinE = BigDecimal.ZERO;
        //本次付款合计金额
//        head.setFd_benCiFuKuanHeJiJinE(paymentAdvanceApply.getOaBorrowMoney());
//        BigDecimal benCiFuKuanHeJiJinE = BigDecimal.ZERO;
        head.setFd_benCiFuKuanHeJiJinE(fd_benCiFuKuanJinE);
        //大写金额
//        head.setFd_daXieJinE(Convert.digitToChinese(paymentAdvanceApply.getOaBorrowMoney()));


        if (CollectionUtils.isNotEmpty(detailDtoList)) {
            for (CreatePaaDetailDto detailDto : detailDtoList) {
                SupplierPayImportDTO.KuanItem.Item item = new SupplierPayImportDTO.KuanItem.Item();
                //采购对账单号/订单号
                item.setFd_caiGouDuiZhangDanHao(detailDto.getPoCode());
                //对账月份 预付款取new date() 邓京术 2024-08-27
                item.setFd_duiZhangYueFen(DateUtil.format(new Date(), "MM"));


                //应付金额
//                BigDecimal discountMoney = detailDto.getDiscountMoney()==null?BigDecimal.ZERO:detailDto.getDiscountMoney();
//                item.setFd_duiZhangDanJinE(detailDto.getItAmount().subtract(discountMoney));
                //对账单金额  = 取页面行“订单含税金额” 2024-08-27 邓京术
                item.setFd_duiZhangDanJinE(detailDto.getItAmount());

                //未付余额
//                item.setFd_weiFuJinE(detailDto.getItAmount().subtract(discountMoney).subtract(detailDto.getAlreadyApplyAmount()));
                //未付余额  取页面的行 可申请金额（ApplyAmount） 2024-08-16 邓京术
                item.setFd_weiFuJinE(detailDto.getApplyAmount());
//                fd_weiFuJinE = fd_weiFuJinE.add(item.getFd_weiFuJinE());


                //TODO 本次未付 本次未付= 未付余额-坏账-尾差调整   2024-08-14根据财务调整  applyAmount - discountMoney 可申请金额 - 折扣金额
//                    item.setFd_benCiWeiFu(detailDto.getItAmount().subtract(detailDto.getAlreadyApplyAmount()));
                item.setFd_benCiWeiFu(detailDto.getApplyAmount().subtract(detailDto.getDiscountMoney()));

                //本次未付合计 = 本次未付金额汇总
                fd_weiFuJinE = fd_weiFuJinE.add(item.getFd_benCiWeiFu());

                //本次付款金额
//                item.setFd_benCiFuKuanJinE(detailDto.getBudOutMoney());
//                fd_benCiFuKuanJinE = fd_benCiFuKuanJinE.add(item.getFd_benCiFuKuanJinE());

                //本次付款金额 = 取页面的本次申请金额(getBudOutMoney) -  行 折扣金额(getDiscountMoney) 2024-08-16 邓京术
                item.setFd_benCiFuKuanJinE(detailDto.getBudOutMoney().subtract(detailDto.getDiscountMoney()));
                //本次付款金额 合计 2024-08-16 邓京术
                fd_benCiFuKuanJinE = fd_benCiFuKuanJinE.add(item.getFd_benCiFuKuanJinE());

                //sap采购对账单号
                item.setFd_sapCaiGouDuiZhangDanHao("");
                //TODO 坏账/外币等扣款  取折扣金额
                item.setFd_huaiZhangHeXiao(detailDto.getDiscountMoney());
//                item.setFd_zheKouJinE(discountMoney.stripTrailingZeros());
                //TODO 尾差调整
                item.setFd_weiChaDiaoZheng(BigDecimal.ZERO);
                //TODO 本次未付 本次未付= 未付余额-坏账-尾差调整
//                item.setFd_benCiWeiFu(detailDto.getItAmount().subtract(detailDto.getAlreadyApplyAmount()));
//                item.setFd_benCiWeiFu(detailDto.getItAmount().subtract(detailDto.getAlreadyApplyAmount()).subtract(discountMoney));
//                item.setFd_benCiWeiFu(detailDto.getApplyAmount().subtract(detailDto.getDiscountMoney()));


                //SAP凭证号
                item.setFd_pingZhengHao("");
                //供应商代码1
                item.setFd_gongYingShangDaiMa1(paymentAdvanceApply.getSupplierCode());
                //供应商1
                item.setFd_gongYingShang1(paymentAdvanceApply.getSupplierName());
                //收款单位1
                item.setFd_shouKuanDanWei1(paymentAdvanceApply.getPaymentCompanyName());
                //开户银行1
                item.setFd_kaiHuYinXing1(paymentAdvanceApply.getSupBankName());
                //银行账号1
                item.setFd_yinXingZhangHao1(paymentAdvanceApply.getSupBankAccount());
                //付款条件1
                DictDTO dictDTO = paymentMethodCache.get(StringUtils.isNotEmpty(detailDto.getPaymentConditionCode()) ? detailDto.getPaymentConditionCode() : "");
                item.setFd_fuKuanTiaoJian1(ObjectUtil.isNotNull(dictDTO) ? dictDTO.getCodeWithDesc() : "");
                //银行行号
                item.setFd_yinHangHao(StringUtils.isNotEmpty(paymentAdvanceApply.getSupBankCode()) ? paymentAdvanceApply.getSupBankCode() : "");
                //银行国际代码
                item.setFd_yinHangCode(StringUtils.isNotEmpty(paymentAdvanceApply.getBankInterCode()) ? paymentAdvanceApply.getBankInterCode() : "");
                //付款到期日 2024-11-06
                item.setFd_daoQiRi(detailDto.getPaymentExpireDate() == null ? "" : DateUtils.formatYYYYMMDDDash(detailDto.getPaymentExpireDate()));
                kuanItemList.add(item);
            }
        }
        kuanItem.setItem(kuanItemList);
        supplierPayImportDTO.setFuKuanItem(kuanItem);
        //2024-08-27修改本次付款金额汇总
        head.setFd_benCiFuKuanHeJiJinE(fd_benCiFuKuanJinE);
        //大写金额
        head.setFd_daXieJinE(Convert.digitToChinese(fd_benCiFuKuanJinE));

        SupplierPayImportDTO.ZongItem zongItem = new SupplierPayImportDTO.ZongItem();
        List<SupplierPayImportDTO.ZongItem.Item> zongItemList = new ArrayList<>();
        SupplierPayImportDTO.ZongItem.Item item = new SupplierPayImportDTO.ZongItem.Item();
        //供应商汇总代码
        item.setFd_gongYingShangHuiZongDaiMa(paymentAdvanceApply.getSupplierCode());
        SupplierDTO supplierDTO = supplierClient.getSupplierByCode(paymentAdvanceApply.getSupplierCode());
        String en = ObjectUtil.isNull(supplierDTO) ? "" : supplierDTO.getSupplierNameEn();
        //供应商汇总收款单位
        List<SupplierBankDTO> supplierBankDTOS = supplierClient.supplierBankDate(paymentAdvanceApply.getSupplierCode());
        if (CollectionUtils.isNotEmpty(supplierBankDTOS)) {
            item.setFd_gongYingShangHuiZongShouKua(StringUtils.isNotEmpty(supplierBankDTOS.get(0).getCompanyName()) ? supplierBankDTOS.get(0).getCompanyName() : "");
        } else {
            item.setFd_gongYingShangHuiZongShouKua("");
        }

        //供应商汇总开户银行
        item.setFd_gongYingShangHuiZongKaiHuYi(paymentAdvanceApply.getSupBankName());
        //供应商汇总银行账号
        item.setFd_gongYingShangHuiZongYinXing(paymentAdvanceApply.getSupBankAccount());
        //银行行号
        item.setFd_yinHangHao(StringUtils.isNotEmpty(paymentAdvanceApply.getSupBankCode()) ? paymentAdvanceApply.getSupBankCode() : "");
        //银行国际代码
        item.setFd_yinHangCode(StringUtils.isNotEmpty(paymentAdvanceApply.getBankInterCode()) ? paymentAdvanceApply.getBankInterCode() : "");
        //本次未付合计
        item.setFd_benCiWeiFuHeJi(fd_weiFuJinE);
        //本次付款金额合计
        item.setFd_benCiFuKuanJinEHeJi(fd_benCiFuKuanJinE);
        zongItemList.add(item);
        zongItem.setItem(zongItemList);
        supplierPayImportDTO.setHuiZongItem(zongItem);

        ApiResult<String> orUpdate = paymentOaClient.supplierPayImport(supplierPayImportDTO);
        final String code = orUpdate.getCode();
        if (code.equals(RestCode.SAP_SUCCESS.getCode())) {
            //成功就更新流程id
            final String oaId = orUpdate.getData();
            paymentAdvanceApply.setOaProcessCode(oaId);
            paymentAdvanceApply.setStatus(3);
            paymentAdvanceApplyService.updateById(paymentAdvanceApply);
        } else {
            throw new DaoException(StrUtil.format("OA接口报错：{}", orUpdate.getMessage()));
        }
    }

    @Override
    public void pushOpen(String ids) {
        List<String> idList = Arrays.asList(StringUtils.split(ids, ","));
//        for (String id : idList) {
//            this.deleteImg(Long.valueOf(id));
//            this.deletePoImg(Long.valueOf(id));
//
//            this.toImg(id);
//            this.toPoImg(Long.valueOf(id));
//        }
        //付款条件
        List<DictDTO> paymentMethods = dictClient.getDicByType(DictCode.PAYMENT_TERMS.getCode());
        final Map<String, DictDTO> paymentMethodCache = paymentMethods.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
        List<PaymentAdvanceApply> paymentCodApplyList = paymentAdvanceApplyService.listByIds(idList);
        if (CollectionUtils.isNotEmpty(paymentCodApplyList)) {

            String accessToken = financialShareUtil.getShareAccessToken();
            for (PaymentAdvanceApply paymentCodApply : paymentCodApplyList) {
                if (ObjectUtil.isNull(paymentCodApply.getPoImgTime())){
                    throw new DaoException("此单据没有影像化编码，请先影像化");
                }
                //增加redis锁如果这个单据的数据正在处理就直接返回
                final String lockKey = PaymentAdvanceLock + paymentCodApply.getApApplyNo();
                if (!redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS)) {
                    log.info("此单据："+paymentCodApply.getApApplyNo()+"正在处理，请稍后提交!");
                    throw new DaoException("此单据："+paymentCodApply.getApApplyNo()+"正在处理，请稍后提交!");
                }
                if (paymentCodApply.getStatus() != 1&&paymentCodApply.getStatus() != 2&&paymentCodApply.getStatus() != 4){
                    throw new DaoException("此单据："+paymentCodApply.getApApplyNo()+"状态不可推送!");
                }
                PayImportToOpenDTO payImportToOpenDTO = new PayImportToOpenDTO();
                PayImportToOpenDTO.DataHead dataHead = new PayImportToOpenDTO.DataHead();
                // 结算组织.编码
                dataHead.setSettleorg_number(paymentCodApply.getCompanyCode());
                // 单据编号
                dataHead.setBillno(paymentCodApply.getApApplyNo());
                // 单据类型.编码
                dataHead.setBilltype_number("ap_payapply_BT_S");
                // 申请日期
                dataHead.setApplydate(LocalDateTimeUtil.format(paymentCodApply.getCreateTime(), "yyyy-MM-dd"));
                // 申请组织.编码
                dataHead.setApplyorg_number(paymentCodApply.getCompanyCode());
                // 采购组织.编码
                dataHead.setPurorg_number(paymentCodApply.getCompanyCode());
                // 付款组织.编码
                dataHead.setPayorg_number(paymentCodApply.getPaymentCompanyCode());
                // 收款供应商.编码
                dataHead.setM4p4_supplier_number(paymentCodApply.getSupplierCode());
                // 供应商开户行
                dataHead.setM4p4_assacct(paymentCodApply.getSupBankName());
                // 开户行账号
                dataHead.setM4p4_deposit_bank(paymentCodApply.getSupBankAccount());
                // 银行代码
                dataHead.setM4p4_bank_code(StringUtils.isNotEmpty(paymentCodApply.getSupBankCode()) ? paymentCodApply.getSupBankCode() : "");
                //收款地址
                dataHead.setM4p4_pay_address(StringUtils.isNotEmpty(paymentCodApply.getBankAddress()) ? paymentCodApply.getBankAddress() : "");
                //收款单位
                dataHead.setM4p4_payee(StringUtils.isNotEmpty(paymentCodApply.getPaymentCompanyName()) ? paymentCodApply.getPaymentCompanyName() : "");
                // 业务类型
                dataHead.setM4p4_business_type(paymentCodApply.getBusinessType());
                // 提前支付 财务康玉华说不需要传 2026-01-17
//                dataHead.setM4p4_advancepayment(String.valueOf(paymentCodApply.getAdvancePaymentFlag()));

                //判断供应商付款金额是否超计划付款，邓京术 2025-08-25

                BigDecimal exceedPlanPayMonthAmount = paymentPlanLogic.findSupplierPaymentPlanSummary(paymentCodApply.getSupplierCode(), paymentCodApply.getCompanyCode(), 2,"S");
                if (exceedPlanPayMonthAmount.floatValue() > 0f) {
            //打上超计划标识，及金额
                    dataHead.setM4p4_ex_pay_plan("1");
                    dataHead.setM4p4_ex_pay_planamt(exceedPlanPayMonthAmount.stripTrailingZeros().toPlainString());
                }else {
                    dataHead.setM4p4_ex_pay_plan("0");
                    dataHead.setM4p4_ex_pay_planamt("0");
                }
//                if (paymentCodApply.getPayPlanMoney() != null && paymentCodApply.getPayPlanMoney().compareTo(BigDecimal.ZERO) > 0) {
//                    if (paymentCodApply.getPayPlanMoney() != null && paymentCodApply.getOaBorrowMoney().compareTo(paymentCodApply.getPayPlanMoney()) > 0) {
//                        dataHead.setM4p4_ex_pay_plan("1");
//                        dataHead.setM4p4_ex_pay_planamt(paymentCodApply.getOaBorrowMoney().subtract(paymentCodApply.getPayPlanMoney()).stripTrailingZeros().toPlainString());
//                    } else {
//                        dataHead.setM4p4_ex_pay_plan("0");
//                        dataHead.setM4p4_ex_pay_planamt("0");
//                    }
//                } else {
//                    dataHead.setM4p4_ex_pay_plan("0");
//                    dataHead.setM4p4_ex_pay_planamt("0");
//                }

                // 付款用途
                dataHead.setM4p4_pay_purpose(paymentCodApply.getPaymentPurposeDesc());
                // 影像文件
                dataHead.setM4p4_image_file(paymentCodApply.getImgCode());
                dataHead.setImageno(paymentCodApply.getImgCode());
                dataHead.setM4p4_image_file(paymentCodApply.getPoImgCode());
                // 承兑期限
                if (StrUtil.isNotEmpty(paymentCodApply.getAcceptanceMethod())) {
                    DictDTO dict = dictClient.getDictByTypeAndCode(DictCode.SUPPLIER_ACCETP_DEADLINE.getCode(), paymentCodApply.getAcceptanceMethod());
                    dataHead.setM4p4_accep_period(ObjectUtil.isNotNull(dict) ? dict.getName() : "");
                } else {
                    dataHead.setM4p4_accep_period("");
                }

                // 报关公司
                dataHead.setM4p4_customs_broker(paymentCodApply.getFaSupplier());
                // 供应商退款
                dataHead.setM4p4_supplier_refund("0");
                if (paymentCodApply.getCompanyCode().equals(paymentCodApply.getPaymentCompanyCode()) && paymentCodApply.getPaymentWayCode().equals("B")) {
                    // 付款方式.编码
                    dataHead.setM4p4_pay_type_number("101");
                } else if (!paymentCodApply.getCompanyCode().equals(paymentCodApply.getPaymentCompanyCode()) && paymentCodApply.getPaymentWayCode().equals("B")) {
                    // 付款方式.编码
                    dataHead.setM4p4_pay_type_number("105");
                } else if (paymentCodApply.getPaymentWayCode().equals("C")) {
                    // 付款方式.编码
                    dataHead.setM4p4_pay_type_number("201");
                } else if (paymentCodApply.getPaymentWayCode().equals("D")) {
                    // 付款方式.编码
                    dataHead.setM4p4_pay_type_number("701");
                }
                // 备注
                dataHead.setM4p4_remarks(paymentCodApply.getApplyRemark());
                // 经办人.工号
                dataHead.setM4p4_handler_number("admin".equals(paymentCodApply.getOaHandlerCode()) ? "ID-000005" : paymentCodApply.getOaHandlerCode());
                dataHead.setCreator_number("admin".equals(LoginUtil.getAccount()) ? "ID-000005" : LoginUtil.getAccount());
                // 付款币种.货币代码
                dataHead.setPaycurrency_number(paymentCodApply.getCurrencyCode());
                // 结算币.货币代码
                dataHead.setSettlecurrency_number(paymentCodApply.getCurrencyCode());
                // 汇率表.编码
//                dataHead.setExratetable_number("");
                // 汇率日期
//                dataHead.setExratedate("");
                // 换算方式
//                dataHead.setQuotation("");

                // 已付款金额
                BigDecimal actualPayAmount = paymentPlanLogic.findSupplierPaymentPlanSummary(paymentCodApply.getSupplierCode(), paymentCodApply.getCompanyCode(), 1,"Y");

                dataHead.setM4p4_amt_paid(actualPayAmount == null ? "0" : actualPayAmount.stripTrailingZeros().toPlainString());
                // 申请金额
                dataHead.setApplyamount(paymentCodApply.getOaBorrowMoney() == null ? "0" : paymentCodApply.getOaBorrowMoney().stripTrailingZeros().toPlainString());
                // 折扣总金额
                dataHead.setM4p4_discount_amt_sum((paymentCodApply.getOaBorrowMoney() == null ? BigDecimal.ZERO : paymentCodApply.getOaBorrowMoney()).subtract(paymentCodApply.getActualityPayMoney() == null ? BigDecimal.ZERO : paymentCodApply.getActualityPayMoney()).stripTrailingZeros().toPlainString());
                // 应付总金额
                dataHead.setM4p4_pay_amt_amt(paymentCodApply.getActualityPayMoney() == null ? "0" : paymentCodApply.getActualityPayMoney().stripTrailingZeros().toPlainString());
                dataHead.setM4p4_ex_planamt(paymentCodApply.getPayPlanMoney() == null ? "0" : paymentCodApply.getPayPlanMoney().stripTrailingZeros().toPlainString());
                dataHead.setM4p4_intelbank_code(StringUtils.isNotEmpty(paymentCodApply.getBankInterCode()) ? paymentCodApply.getBankInterCode() : "");
                // 申请金额折结算币
//                dataHead.setAppseleamount("");
//                // 交易类型.编码
//                dataHead.setM4p4_crosstrantype_number("");
//                // 核准金额
                dataHead.setApprovalamount(paymentCodApply.getActualityPayMoney()== null ? "0" : paymentCodApply.getActualityPayMoney().stripTrailingZeros().toPlainString());
                //逾期款项
                dataHead.setM4p4_overdue_payamt(paymentCodApply.getOverdueAmount() == null ? "0" : paymentCodApply.getOverdueAmount().stripTrailingZeros().toPlainString());
                //到期款项
                dataHead.setM4p4_due_payamt(paymentCodApply.getDueAmount() == null ? "0" : paymentCodApply.getDueAmount().stripTrailingZeros().toPlainString());
                //应付账款余额
                dataHead.setM4p4_ac_paybalance(paymentCodApply.getAccountsPayableBalance() == null ? "0" : paymentCodApply.getAccountsPayableBalance().stripTrailingZeros().toPlainString());
                //暂估余额
                dataHead.setM4p4_estimate_balance(paymentCodApply.getProvisionalBalance() == null ? "0" : paymentCodApply.getProvisionalBalance().stripTrailingZeros().toPlainString());
                //代收
                dataHead.setM4p4_collection(String.valueOf(paymentCodApply.getCollectionFlag()));
                //                // 核准金额折结算币
//                dataHead.setAprseleamount("");
                //代收供应商
                dataHead.setM4p4_agency_supplier_number(paymentCodApply.getPaymentSupplierCode());
                //TODO
                dataHead.setFeepayer(paymentCodApply.getFeePayer());
                dataHead.setM4p4_pay_behalf(paymentCodApply.getCompanyCode().equals(paymentCodApply.getPaymentCompanyCode())?"0":"1");
                dataHead.setM4p4_prepaid_method(String.valueOf(paymentCodApply.getAdvanceType()));
                dataHead.setM4p4_emergency_degree(String.valueOf(paymentCodApply.getUrgentFlag()));

                List<PayImportToOpenDTO.Entry> entryList = new ArrayList<>();

                List<CreatePaaDetailDto> pcaDetailList = paymentAdvanceApplyDetailLogic.findPaaDetailListByPaaIdAndType(paymentCodApply.getId(), 1);
                for (CreatePaaDetailDto pcaDetail : pcaDetailList) {
                    PayImportToOpenDTO.Entry entry = new PayImportToOpenDTO.Entry();
                    // 明细.摘要
                    entry.setId("202-" + String.valueOf(pcaDetail.getId()));
                    entry.setM4p4_summary(pcaDetail.getItemRemark());
                    // 明细.付款条件
                    DictDTO dictDTO = paymentMethodCache.get(StringUtils.isNotEmpty(pcaDetail.getPaymentConditionCode()) ? pcaDetail.getPaymentConditionCode() : "");
                    entry.setM4p4_pay_term(ObjectUtil.isNotNull(dictDTO) ? dictDTO.getName() : "");
                    // 明细.报关公司
                    entry.setM4p4_custom_broker(pcaDetail.getSupplierCode2());
                    // 明细.已申请金额
                    entry.setM4p4_applied_amt(pcaDetail.getAlreadyApplyAmount() == null ? "0" : pcaDetail.getAlreadyApplyAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.折扣金额
                    entry.setM4p4_discount_amt(pcaDetail.getDiscountMoney() == null ? "0" : pcaDetail.getDiscountMoney().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.本次申请金额
                    entry.setM4p4_applied_amt_e(pcaDetail.getBudOutMoney() == null ? "0" : pcaDetail.getBudOutMoney().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.可申请金额
                    entry.setM4p4_applied_amt_a(pcaDetail.getApplyAmount() == null ? "0" : pcaDetail.getApplyAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.冲账金额
                    entry.setM4p4_offset_amt(pcaDetail.getReversalMoney() == null ? "0" : pcaDetail.getReversalMoney().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.付款到期日
                    entry.setM4p4_pay_due_date(pcaDetail.getPaymentExpireDate() == null ? null : LocalDateTimeUtil.format(pcaDetail.getPaymentExpireDate(), "yyyy-MM-dd"));
                    // 明细.付款到期日
                    entry.setE_expaydate(pcaDetail.getExpectationPaymentDate() == null ? "" : LocalDateTimeUtil.format(pcaDetail.getExpectationPaymentDate(), "yyyy-MM-dd"));
                    // 明细.采购组
//                    if (StrUtil.isNotEmpty(pcaDetail.getPurchaseGroup())){
//                        PurchaseGroupDTO purchaseGroupDTO = purchaseGroupClient.getByCode(pcaDetail.getPurchaseGroup());
//                        entry.setM4p4_procure_group(ObjectUtil.isNotNull(purchaseGroupDTO)?StrUtil.format("({}){}",purchaseGroupDTO.getPurchaseGroupCode(),purchaseGroupDTO.getPurchaseGroupName()):"");
//                    }else {
                    entry.setM4p4_procure_group(pcaDetail.getBuyer());
//                    }
                    entry.setM4p4_purchase_order_num(pcaDetail.getPoCode());
                    // 明细.开票申请单号
                    entry.setM4p4_inv_apply("");
                    // 明细.对账单号
                    entry.setM4p4_statementnumber("");
                    // 明细.申请金额
                    entry.setE_applyamount(pcaDetail.getBudOutMoney() == null ? "0" : pcaDetail.getBudOutMoney().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    //含税金额
                    entry.setM4p4_taxandamt(pcaDetail.getItAmount() == null ? "0" : pcaDetail.getItAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    // 明细.税率
                    TaxDTO taxDTO = taxClient.getByCode(pcaDetail.getTaxCode());
                    if (ObjectUtil.isNotNull(taxDTO)) {
                        //获取taxName中的数字，前面加上V
                        String taxCode = "V" + taxDTO.getTaxName().chars()
                                .filter(Character::isDigit)
                                .mapToObj(c -> String.valueOf((char) c))
                                .collect(Collectors.joining());

                        entry.setM4p4_taxrate_number(taxCode);
                    }
                    // 明细.申请金额折结算币
//                    entry.setE_appseleamount("");
                    //TODO 付款类型.编码
                    entry.setE_paymenttype_number("202");
                    // 明细.往来类型
                    entry.setE_asstacttype("bd_supplier");
                    // 往来户.编码
                    entry.setE_asstact_number(paymentCodApply.getSupplierCode());
                    entry.setE_settlementtype_number(dataHead.getM4p4_pay_type_number());
                    entry.setM4p4_supplier_number(paymentCodApply.getSupplierCode());
                    entry.setM4p4_purchase_row(pcaDetail.getPoItemNo());
                    if (pcaDetail.getDiscountMoney()==null){
                        pcaDetail.setDiscountMoney(BigDecimal.ZERO);
                    }
                    // 结算方式.编码
//                    entry.setE_settlementtype_number("");
                    // 明细.实际应付金额
                    entry.setE_payamount(pcaDetail.getBudOutMoney().stripTrailingZeros().toPlainString());
                    // 明细.核准金额
                    entry.setE_approvedamt(pcaDetail.getBudOutMoney().subtract(pcaDetail.getDiscountMoney()).setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    //明细.对账影像
                    entry.setM4p4_reconcilia_image("");
                    //明细.开票影像
                    entry.setM4p4_invoice_image("");
                    // 明细.核准金额折结算币
//                    entry.setE_approvedseleamt("");

                    entryList.add(entry);
                }
                dataHead.setEntry(entryList);


                List<PayImportToOpenDTO.Entry2> entryList2 = new ArrayList<>();
                PayImportToOpenDTO.Entry2 entry2 = new PayImportToOpenDTO.Entry2();
//                entry2.setId(IdWorker.getIdStr());
                entry2.setM4p4_complete(String.valueOf(paymentCodApply.getPoSatisfyFlag()));
                entry2.setM4p4_attachment_type("采购订单");
                entryList2.add(entry2);

                if (paymentCodApply.getAdvanceType() != 0&&paymentCodApply.getCurrencyCode().equals("CNY")){
                    PayImportToOpenDTO.Entry2 entry33 = new PayImportToOpenDTO.Entry2();
//                entry2.setId(IdWorker.getIdStr());
                    entry33.setM4p4_complete(String.valueOf(paymentCodApply.getPoSatisfyFlag()));
                    entry33.setM4p4_attachment_type("送货单");
                    entryList2.add(entry33);
                }


                dataHead.setM4p4_3ord_matc_entry(entryList2);

                //pcaDetailList中根据期望付款日进行分组
                Map<LocalDateTime, List<CreatePaaDetailDto>> pcaDetailListMap = pcaDetailList.stream().collect(Collectors.groupingBy(CreatePaaDetailDto::getExpectationPaymentDate));
                List<PayImportToOpenDTO.Entry3> entryList3 = new ArrayList<>();
                pcaDetailListMap.forEach((key, value) -> {
                    //根据期望付款日统计本次申请金额
                    BigDecimal applyAmount = BigDecimal.ZERO;
                    BigDecimal autalApplyAmount = BigDecimal.ZERO;
                    for (CreatePaaDetailDto pcaDetail : value){
                        if (pcaDetail.getDiscountMoney()==null){
                            pcaDetail.setDiscountMoney(BigDecimal.ZERO);
                        }
                        applyAmount = applyAmount.add(pcaDetail.getBudOutMoney());
                        autalApplyAmount = autalApplyAmount.add(pcaDetail.getBudOutMoney().subtract(pcaDetail.getDiscountMoney()));
                    }
                    //根据期望付款日合并订单单号+行号，“/”隔开
                    Set<String> accountStatementNos = value.stream().map(item -> (item.getPoCode() != null ? item.getPoCode() : "")).collect(Collectors.toSet());
                    //accountStatementNos用“/”隔开
                    String accountStatementNo = accountStatementNos.stream().collect(Collectors.joining("/"));
                    PayImportToOpenDTO.Entry3 entry3 = new PayImportToOpenDTO.Entry3();
                    entry3.setM4p4_approved_amount(autalApplyAmount.stripTrailingZeros().toPlainString());
                    entry3.setM4p4_purchase_num(accountStatementNo);
                    entry3.setM4p4_ex_payment_date(LocalDateTimeUtil.format( key, "yyyy-MM-dd"));
                    entry3.setM4p4_settlement_modes_number(dataHead.getM4p4_pay_type_number());
                    entry3.setM4p4_srm_entry_id(String.valueOf(value.get(0).getId()));

                    entry3.setSeq(String.valueOf(value.get(0).getId()));
                    entry3.setE_paymenttype_number("202");
                    entry3.setE_asstact_number(paymentCodApply.getSupplierCode());
                    entry3.setE_applyamount(applyAmount.stripTrailingZeros().toPlainString());
                    entry3.setE_asstacttype("bd_supplier");
                    entryList3.add(entry3);
                });
                dataHead.setM4p4_srm_entry(entryList3);

                payImportToOpenDTO.setData(dataHead);
                ErpApiResult<PayImportToOpenResultDTO> result = paymentOaClient.payImportToOpen(accessToken, payImportToOpenDTO);
                if (!result.getStatus()) {
                    redisTemplate.delete(lockKey);
                    throw new DaoException("金蝶系统接口报错：" + result.getMessage());
                }
                String id = result.getData().getResult().get(0).getId();
                String code = result.getData().getResult().get(0).getNumber();
                paymentCodApply.setOaProcessId(id);
                paymentCodApply.setOaProcessCode(code);
                paymentCodApply.setStatus(3);
                paymentAdvanceApplyService.updateById(paymentCodApply);
                redisTemplate.delete(lockKey);
            }
        }
    }



    @Override
    public String importData(MultipartFile file) {
        List<PaymentAdvanceApplyImportDTO> cachedDataList = ListUtils.newArrayList();
        List<PaymentAdvanceApplyImportResultDTO> resultDTOS = ListUtils.newArrayList();
        try {
            //工厂
            final List<FactoryDTO> all = factoryClient.getAll();
            final Map<String, FactoryDTO> factoryCache = all.stream()
                    .collect(Collectors.toMap(FactoryDTO::getFactory, a -> a));
            final Set<String> factoryCodes = factoryCache.keySet();
            //币种
            List<DictDTO> currencys = dictClient.getDicByType(DictCode.CURRENCY.getCode());
            final Map<String, DictDTO> currencyCache = currencys.stream().collect(Collectors.toMap(DictDTO::getCode, a -> a));
            final Set<String> currencyCodes = currencyCache.keySet();
            //付款方式
            List<DictDTO> paymentWays = dictClient.getDicByType(DictCode.PAYMENT_WAY.getCode());
            final Map<String, DictDTO> paymentWayCache = paymentWays.stream().collect(Collectors.toMap(DictDTO::getName, a -> a));
            final Set<String> paymentWayCodes = paymentWayCache.keySet();
            EasyExcel.read(file.getInputStream(), PaymentAdvanceApplyImportDTO.class,
                    new ReadListener<PaymentAdvanceApplyImportDTO>() {
                        @Override
                        public void invoke(PaymentAdvanceApplyImportDTO data, AnalysisContext context) {
                            String result = "";
                            if (Strings.isNullOrEmpty(data.getPoCode())) {
                                result += "采购订单号为空；";
                            }
                            if (Strings.isNullOrEmpty(data.getPoItemNo())) {
                                result += "订单行号为空；";
                            }
//                            if (Strings.isNullOrEmpty(data.getFactoryCode())) {
//                                result+="工厂为空；";
//                            } else if (!factoryCodes.contains(data.getFactoryCode())){
//                                result+=StrUtil.format("工厂：{}在系统中不存在；",data.getFactoryCode());
//                            }
                            if (StringUtils.isNotEmpty(data.getPoCode()) && StringUtils.isNotEmpty(data.getPoItemNo())) {
                                PurchaseDetailDTO purchaseDetailDTO = purchaseOrderClient.getOrderDetailByCodeAndItemNo(data.getPoCode(), data.getPoItemNo());
                                if (ObjectUtil.isNull(purchaseDetailDTO)) {
                                    result += StrUtil.format("采购订单号：{}，行号：{}在系统中不存在；", data.getPoCode(), data.getPoItemNo());
                                } else {
                                    PurchaseOrderDTO purchaseOrderDTO = purchaseOrderClient.getOrderByCode(data.getPoCode());
                                    if (ObjectUtil.isNull(purchaseOrderDTO)) {
                                        result += StrUtil.format("采购订单号：{}在系统中不存在；", data.getPoCode());
                                    } else {
                                        data.setFactoryCode(purchaseDetailDTO.getFactoryCode());
                                        data.setPurchaseDetailDTO(purchaseDetailDTO);
                                        data.setCompanyCode(purchaseOrderDTO.getCompanyCode());
                                        data.setSupplierCode(purchaseOrderDTO.getSupplierErpCode());
                                        data.setSupplierName(purchaseOrderDTO.getSupplierName());
                                        data.setPurchaseOrderDTO(purchaseOrderDTO);
//                                        data.setPaymentWayCodeDesc(purchaseOrderDTO.getPaymentMethodName());
//                                        data.setIpwCode(purchaseOrderDTO.getPaymentMethod());
                                    }
                                }
                            }
//                            if (Strings.isNullOrEmpty(data.getCompanyCode())) {
//                                result+="公司为空；";
//                            }
//                            if (Strings.isNullOrEmpty(data.getSupplierCode())) {
//                                result+="供应商编码为空；";
//                            }else {
//                                SupplierDTO supplierDTO = supplierClient.getSupplierByCode(data.getSupplierCode());
//                                if (ObjectUtil.isEmpty(supplierDTO)){
//                                    result+=StrUtil.format("供应商编码：{}在系统中不存在；",data.getSupplierCode());
//                                }else {
//                                    data.setSupplierName(supplierDTO.getSupplierName());
//                                }
//                            }
                            if (Strings.isNullOrEmpty(data.getCurrencyCode())) {
                                result += "币种为空；";
                            } else if (!currencyCodes.contains(data.getCurrencyCode())) {
                                result += StrUtil.format("币种：{}在系统中不存在；", data.getCurrencyCode());
                            }
                            if (!Strings.isNullOrEmpty(data.getPaymentWayCodeDesc())) {
                                if (!paymentWayCodes.contains(data.getPaymentWayCodeDesc())) {
                                    result += StrUtil.format("付款方式：{}在系统中不存在；", data.getPaymentWayCodeDesc());
                                } else {
                                    DictDTO dictDTO = paymentWayCache.get(data.getPaymentWayCodeDesc());
                                    data.setPaymentWayCode(dictDTO.getCode());
                                    data.setIpwCode(data.getPaymentWayCode());
                                }
                            }
//                            if (Strings.isNullOrEmpty(data.getSupBankName())) {
//                                result+="供应商开户行为空；";
//                            }
//                            if (Strings.isNullOrEmpty(data.getSupBankAccount())) {
//                                result+="开户行账号为空；";
//                            }
//                            if (Strings.isNullOrEmpty(data.getBankCode())) {
//                                result+="银行代码为空；";
//                            }else {
//                                data.setSupBankCode(data.getBankCode());
//                            }

                            if (Strings.isNullOrEmpty(data.getBudOutMoneyStr())) {
                                result += "本次申请金额为空；";
                            } else {
                                if (!isValidCurrency(data.getBudOutMoneyStr().replaceAll(",", ""))) {
                                    result += StrUtil.format("本次申请金额：{}格式不正确；", data.getBudOutMoneyStr());
                                } else {
                                    data.setBudOutMoney(new BigDecimal(data.getBudOutMoneyStr().replaceAll(",", "")));
                                    data.setOaBorrowMoney(new BigDecimal(data.getBudOutMoneyStr().replaceAll(",", "")));
                                    data.setOaAleradyPayMoney(new BigDecimal(data.getBudOutMoneyStr().replaceAll(",", "")));
                                }
                            }

                            if (!Strings.isNullOrEmpty(data.getReversalMoneyStr())) {
                                if (!isValidCurrency(data.getReversalMoneyStr().replaceAll(",", ""))) {
                                    result += StrUtil.format("已冲账金额：{}格式不正确；", data.getReversalMoneyStr());
                                } else {
                                    data.setReversalMoney(new BigDecimal(data.getReversalMoneyStr().replaceAll(",", "")));
                                }
                            }

                            if (StringUtils.isNotEmpty(result)) {
                                resultDTOS.add(PaymentAdvanceApplyImportResultDTO.builder().poCode(data.getPoCode()).poItemNo(data.getPoItemNo()).supplierCode(data.getSupplierCode()).budOutMoneyStr(data.getBudOutMoneyStr()).result(result).build());
                            } else {
                                data.setStatus(5);
                                data.setCreateTime(LocalDateTime.now());
                                data.setCreateUserId(LoginUtil.getUserId());
                                data.setCreateUserCode(LoginUtil.getAccount());
                                data.setCreateUserName(LoginUtil.getName());


                                cachedDataList.add(data);
                            }
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        }
                    }).sheet().doRead();
        } catch (IOException e) {
            throw new DaoException("导入失败！");
        }
        if (CollectionUtil.isEmpty(cachedDataList) && CollectionUtil.isEmpty(resultDTOS)) {
            throw new DaoException("导入数据为空！");
        }
        if (CollectionUtil.isNotEmpty(cachedDataList)) {
            for (PaymentAdvanceApplyImportDTO paymentAdvanceApplyImportDTO : cachedDataList) {
                PaymentAdvanceApply paymentAdvanceApply = paymentAdvanceApplyConvert.importDTO2Entity(paymentAdvanceApplyImportDTO);
                String orderCode = sequenceClient.getCodeSequenceNo("payment_advance_apply", 4);
                paymentAdvanceApply.setApApplyNo(orderCode);
                paymentAdvanceApplyService.save(paymentAdvanceApply);

                PurchaseDetailDTO purchaseDetailDTO = paymentAdvanceApplyImportDTO.getPurchaseDetailDTO();
                PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyConvert.importDTO2DetailEntity(paymentAdvanceApplyImportDTO);
                paymentAdvanceApplyDetail.setAppId(paymentAdvanceApply.getId());
                paymentAdvanceApplyDetail.setAppNo(orderCode);
                paymentAdvanceApplyDetail.setItemNo("1");
                paymentAdvanceApplyDetail.setPoNum(purchaseDetailDTO.getNum());
                paymentAdvanceApplyDetail.setMaterialCode(purchaseDetailDTO.getMaterialCode());
                paymentAdvanceApplyDetail.setMaterialDesc(purchaseDetailDTO.getMaterialName());
                paymentAdvanceApplyDetail.setMaterialUnit(purchaseDetailDTO.getUnitCode());
                paymentAdvanceApplyDetail.setTaxCode(purchaseDetailDTO.getTaxCode());
                paymentAdvanceApplyDetail.setTaxDesc(purchaseDetailDTO.getTaxName());
                paymentAdvanceApplyDetail.setTaxValue(BigDecimal.valueOf(purchaseDetailDTO.getTaxValue()));
                paymentAdvanceApplyDetail.setItPrice(purchaseDetailDTO.getPrice());
                paymentAdvanceApplyDetail.setItAmount(purchaseDetailDTO.getTaxAmount());
                PurchaseOrderDTO purchaseOrderDTO = paymentAdvanceApplyImportDTO.getPurchaseOrderDTO();
                paymentAdvanceApplyDetail.setPaymentConditionCode(purchaseOrderDTO.getPaymentMethod());
                paymentAdvanceApplyDetail.setPaymentConditionDesc(purchaseOrderDTO.getPaymentMethodName());
                paymentAdvanceApplyDetail.setDataKey(paymentAdvanceApplyImportDTO.getPoCode() + "_" + paymentAdvanceApplyImportDTO.getPoItemNo());
                paaDetailService.save(paymentAdvanceApplyDetail);
            }
        }
        if (CollectionUtil.isNotEmpty(resultDTOS)) {
            //创建导出动态列
            List<ExportDataDTO> exportDataDTOS = new ArrayList<>();
            exportDataDTOS.add(ExportDataDTO.builder().title("采购订单号").field("poCode").build());
            exportDataDTOS.add(ExportDataDTO.builder().title("订单行号").field("poItemNo").build());
            exportDataDTOS.add(ExportDataDTO.builder().title("供应商编码").field("supplierCode").build());
            exportDataDTOS.add(ExportDataDTO.builder().title("本次申请金额").field("budOutMoneyStr").build());
            exportDataDTOS.add(ExportDataDTO.builder().title("错误信息").field("result").build());
            try {
                //创建导出文件
                File file1 = fileClient.createFile("预付款申请导入错误记录-" + DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN) + ".xlsx");
                //写入错误信息到excel文件
                EasyExcelUtils.trendsModelWriteFile(file1, "sheet", resultDTOS, exportDataDTOS);
                //上传文件
                FileResposeCDTO fileResposeCDTO = fileClient.uploadFile(file1);
                //返回文件id供下载
                return String.valueOf(fileResposeCDTO.getId());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            return "ok";
        }
    }

    @Override
    public PageView paaOrderListByPage(PaymentApplyHeadQuery query) {
        final Page<PaymentAdvanceRefundTransferApplyPO> dbPage = PageUtil.toPage(query);
        //查询预付款信息
        List<PaymentAdvanceRefundTransferApplyPO> poList = paymentAdvanceApplyService.paaOrderListByPage(dbPage, query);
        List<String> dataKeys = poList.stream().map(po -> po.getAppNo() + "_" + po.getItemNo()).collect(Collectors.toList());// 用 "_" 拼接两个字段

        List<String> queryDataKeys = poList.stream().map(po -> po.getDataKey()).collect(Collectors.toList());// 用 "_" 拼接两个字段

        //2025-09-02新增订单过滤逻辑
        //1.通过预付款采购订单号+采购订单行到物料凭证表中找到对应的订单明细物料数据，如果没有查到物料凭证信息，数据通过，如果找到物料凭证信息，则判断是否存在对账单号
        //2.存在对账单号(存在一个订单信息有多个对账单号)，在到开票信息表里查找是否有已经财务确认的开票信息，存在数据则合格，不存在则过滤掉
        //计算转单或者退款 可登记含税金额（cantRegistTaxAmount） 及已登记含税金额（registTaxAmount） 已冲账金额 reversalMoney
        //1.可登记含税金额 = 预付款申请明细中的“本次申请金额”- 预付款申请明细中的“已冲账金额”- 预付款变更单已登记金额（包括退款和转单）。
        if (CollectionUtils.isNotEmpty(dataKeys)) {
            //如果是转单类型
            if (StringUtils.isNotEmpty(query.getDataType()) && "0".equals(query.getDataType())) {
                //全部的物料信息
                List<StatementItemPO> poVoucherList = receiveVoucherService.queryMaterialDocReconciliationInfo(query.getCompanyCode(), queryDataKeys);
                List<String> excludeOrder = new ArrayList<>();
                List<String> orderAll = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(poVoucherList)) {
                    for (StatementItemPO itemPO : poVoucherList) {
                        if (StringUtils.isEmpty(itemPO.getAsNo())) {
                            excludeOrder.add(itemPO.getPoCode() + "_" + itemPO.getPoItemNo());
                        }
                        orderAll.add(itemPO.getPoCode() + "_" + itemPO.getPoItemNo());
                    }
                    //对比出没有物料入库凭证的订单号+订单号
                    List<String> tempList = new ArrayList<>(queryDataKeys);
                    tempList.removeAll(orderAll); //得到的是没有入库凭证的订单号+行号

                    //订单号+订单行，物料凭证只要存在未对账、或对账未开票、或开票财务未确认，都排除
                    List<String> poCodeItemNoList = poVoucherList.stream()
                            .map(item -> item.getPoCode() + "_" + item.getPoItemNo())
                            .collect(Collectors.toList());
                    //排除物料入库凭证明细种存在没有对账单的订单.

                    if (CollectionUtils.isNotEmpty(excludeOrder)) {
                        orderAll.removeAll(excludeOrder);//删除没有对账单的订单+订单号
                    }

                    //2.判断物料入库凭证是否都有对账单号，如果同一个采购订单号+订单行号，存在没有对账单号的，则排除该数据
                    //找出相同 poCode+poItemNo 组合的数据条数 > 1，且这些数据中 asNo 没有值的数据，找到它的订单号+订单行 直接删除改订单号+订单行的预付款
//                        List<String> duplicateComboWithNoAsNo = findDuplicateComboWithNoAsNo(poVoucherList);
//                        //找出 poCode+poItemNo 组合只出现一次且 asNo 没有值的数据直接删除改订单号+订单行的预付款
//                        List<String> singleComboWithNoAsNo = findSingleComboWithNoAsNo(poVoucherList);
//
//                        // 推荐初始化方式（避免多次扩容）
//                        Set<String> combinedSet = new HashSet<>(duplicateComboWithNoAsNo.size() + singleComboWithNoAsNo.size());
//                        combinedSet.addAll(duplicateComboWithNoAsNo);
//                        combinedSet.addAll(singleComboWithNoAsNo);
//                        //删除不符合的数据，留下的进入下一个判断
//                        List<String> result = poCodeItemNoList.parallelStream()
//                                .filter(element -> !combinedSet.contains(element))
//                                .collect(Collectors.toList());
                    //判断对账单对应的开票申请单，财务是否已确认，如果财务未确认，则订单不允许转单。
                    List<String> asNos = extractAsNo(poVoucherList, orderAll);
                    if (CollectionUtils.isNotEmpty(asNos)) {
                        //获取对账单以开票且财务已确认的数据
                        List<InvoicedApplyPO> invoicedApplyPOS = invoicedApplyService.selectDataByAccountStatementNo(asNos);
                        //已开票的订单号+订单行
                        List<String> matchesOrder = extractMatchingKeys(poVoucherList, invoicedApplyPOS);
                        //从预付款列表中只保留和服条件的订单号+行号的数据
                        matchesOrder.addAll(tempList);
                        dataKeys = filterAndCombine(poList, matchesOrder);
                        poList = filterEnt(poList, dataKeys);
                    } else {
                        dataKeys = filterAndCombine(poList, tempList);
                        poList = filterEnt(poList, dataKeys);
                    }
                }
            }
            //当类型为退款时过滤，预付款已经创建过转单的数据
            if (StringUtils.isNotEmpty(query.getDataType()) && "1".equals(query.getDataType())) {
                List<PaymentAdvanceRefundTransferApplyAndDetailListDTO> dataTypeInfoByDateKey = paymentAdvanceRefundTransferApplyDetailLogic.findRefundTransferApplyDataTypeInfoByDateKey(queryDataKeys);
                if (CollectionUtils.isNotEmpty(dataTypeInfoByDateKey)) {
                    Set<String> validDataKeys = dataTypeInfoByDateKey.stream()
                            .map(PaymentAdvanceRefundTransferApplyAndDetailListDTO::getDataKey)
                            .collect(Collectors.toSet());
                    poList.removeIf(po -> {
                        String currentKey = po.getAppNo() + "_" + po.getItemNo();
                        return validDataKeys.contains(currentKey);
                    });
                    dataKeys = poList.stream().map(po -> po.getAppNo() + "_" + po.getItemNo()).collect(Collectors.toList());
                }
            }

            poList.forEach(item -> {
                //已登记含税金额相加
                //   item.setRegistTaxAmount(item.getBudOutMoney() == null ? BigDecimal.ZERO : item.getBudOutMoney().add(item.getReversalMoney() == null ? BigDecimal.ZERO : item.getReversalMoney()));
                //可登记含税金额相减
                item.setCantRegistTaxAmount(item.getBudOutMoney() == null ? BigDecimal.ZERO : item.getBudOutMoney().subtract(item.getReversalMoney() == null ? BigDecimal.ZERO : item.getReversalMoney()));
                item.setRegistTaxAmount(BigDecimal.ZERO);
            });
            if (CollectionUtils.isNotEmpty(dataKeys)) {
                List<PaymentAdvanceRefundTransferApplyAndDetailListDTO> details = paymentAdvanceRefundTransferApplyDetailLogic.findRefundTransferApplyDetailByDateKey(dataKeys);
                if (CollectionUtils.isNotEmpty(details)) {
                    //进行比较和计算
                    Map<String, BigDecimal> poCodeToSumMap = details.stream()
                            .collect(Collectors.groupingBy(
                                    PaymentAdvanceRefundTransferApplyAndDetailListDTO::getDataKey,
                                    Collectors.reducing(BigDecimal.ZERO,
                                            dto -> Objects.requireNonNullElse(dto.getTheRegistTaxAmount(), BigDecimal.ZERO),
                                            BigDecimal::add)
                            ));
                    poList.forEach(item -> {
                        String dataKey = item.getAppNo() + "_" + item.getItemNo();
                        //已登记含税金额
                        BigDecimal sum = poCodeToSumMap.getOrDefault(dataKey, BigDecimal.ZERO);
                        item.setRegistTaxAmount(sum);
                        //可登记含税金额
                        item.setCantRegistTaxAmount(item.getCantRegistTaxAmount().subtract(sum));
                    });
                }
            }
            poList.removeIf(item -> item.getCantRegistTaxAmount().compareTo(BigDecimal.ZERO) <= 0);
        }

        List<PaymentAdvanceRefundTransferApplyAndDetailListDTO> dtoList = paymentAdvanceApplyConvert.paaPOToDTOList(poList);

        Page<PaymentAdvanceRefundTransferApplyAndDetailListDTO> toPage = new Page<>(1, dtoList.size());
        toPage.setRecords(dtoList);
        toPage.setTotal(dtoList.size());
        return PageUtil.getPV(toPage);
    }


    public List<String> filterAndCombine(
            List<PaymentAdvanceRefundTransferApplyPO> poList,
            List<String> dataKeyList) {
        Set<String> dataKeySet = new HashSet<>(dataKeyList);
        return poList.stream()
                .filter(po ->
                        po.getDataKey() != null && // 处理null值
                                dataKeySet.contains(po.getDataKey()))
                .map(po -> {
                    String appNo = po.getAppNo() != null ? po.getAppNo() : "";
                    String itemNo = po.getItemNo() != null ? po.getItemNo() : "";
                    return appNo + "_" + itemNo;
                })
                .collect(Collectors.toList());
    }

    public List<PaymentAdvanceRefundTransferApplyPO> filterEnt(
            List<PaymentAdvanceRefundTransferApplyPO> poList,
            List<String> dataKeyList) {
        Set<String> keySet = new HashSet<>(dataKeyList);

        // 2. 使用Stream处理过滤和转换
        return poList.stream()
                // 过滤条件：拼接的AppNo_ItemNo存在于keySet中
                .filter(po -> {
                    return keySet.contains(po.getAppNo() + "_" + po.getItemNo());
                })
                // 直接返回符合条件的PO对象列表
                .collect(Collectors.toList());
    }

    /**
     * 符合的订单行数据
     *
     * @param poVoucherList
     * @param invList
     * @return
     */
    public static List<String> extractMatchingKeys(
            List<StatementItemPO> poVoucherList,
            List<InvoicedApplyPO> invList) {

        // 1. 提取invList中的accountStatementNo到HashSet（O(1)查询）
        Set<String> targetAccounts = invList.stream()
                .map(InvoicedApplyPO::getAccountStatementNo)
                .filter(account -> account != null && !account.isEmpty()) // 可选空值过滤
                .collect(Collectors.toSet());

        // 2. 过滤poVoucherList并拼接PoCode+PoItemNo
        return poVoucherList.stream()
                // 3. 筛选asNo存在于targetAccounts中的记录
                .filter(item -> item.getAsNo() != null && targetAccounts.contains(item.getAsNo()))
                // 4. 拼接PoCode+PoItemNo
                .map(item -> item.getPoCode() + "_" + item.getPoItemNo())
                // 5. 可选去重（根据业务需求决定）
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 过滤物料实体符合的数据的对账单号List
     *
     * @param poVoucherList
     * @param list
     * @return
     */
    public static List<String> extractAsNo(List<StatementItemPO> poVoucherList, List<String> list) {
        // 将list转换为HashSet以提高查询效率
        Set<String> targetKeys = new HashSet<>(list);

        return poVoucherList.stream()
                // 拼接PoCode和PoItemNo作为键
                .map(item -> item.getPoCode() + "_" + item.getPoItemNo())
                // 过滤出存在于list中的键
                .filter(targetKeys::contains)
                // 回到原始对象获取asNo（需要重新关联原始对象）
                .map(key -> {
                    // 根据拼接的key反向查找原始对象（注意：这里假设key在poVoucherList中唯一）
                    // 实际业务中可能需要根据业务逻辑处理重复key的情况
                    return poVoucherList.stream()
                            .filter(item -> (item.getPoCode() + "_" + item.getPoItemNo()).equals(key))
                            .findFirst()
                            .map(StatementItemPO::getAsNo)
                            .orElse(null);
                })
                // 过滤掉可能出现的null值（根据业务需求决定是否保留）
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 找出 poCode+poItemNo 组合只出现一次且 asNo 没有值的数据
     */
    public static List<String> findSingleComboWithNoAsNo(List<StatementItemPO> list) {
        // 按 poCode+poItemNo 组合分组
        Map<String, List<StatementItemPO>> groupedByCombo = list.stream()
                .collect(Collectors.groupingBy(
                        item -> item.getPoCode() + "_" + item.getPoItemNo()
                ));

        return groupedByCombo.entrySet().stream()
                // 筛选组合只出现一次的组
                .filter(entry -> entry.getValue().size() == 1)
                // 获取组内元素
                .flatMap(entry -> entry.getValue().stream())
                // 筛选 asNo 为空或的记录
                .filter(item -> StringUtils.isEmpty(item.getAsNo()))
                .map(item -> item.getPoCode() + "_" + item.getPoItemNo())  // 新增的map操作
                .distinct()  // 关键去重操作
                .collect(Collectors.toList());
    }

    /**
     * 找出相同 poCode+poItemNo 组合的数据条数 > 1，且这些数据中 asNo 没有值的数据
     */
    public static List<String> findDuplicateComboWithNoAsNo(List<StatementItemPO> list) {
        // 1. 按 poCode+poItemNo 组合分组
        Map<String, List<StatementItemPO>> groupedByCombo = list.stream()
                .collect(Collectors.groupingBy(
                        item -> item.getPoCode() + "_" + item.getPoItemNo()
                ));

        // 2. 筛选出组合数据条数 > 1 的组合key
        Set<String> duplicateComboKeys = groupedByCombo.entrySet().stream()
                .filter(entry -> entry.getValue().size() > 1)
                .map(Map.Entry::getKey)
                .collect(Collectors.toSet());

        // 3. 从原始列表中筛选出这些组合中 asNo 没有值的记录
        return list.stream()
                .filter(item -> duplicateComboKeys.contains(item.getPoCode() + "_" + item.getPoItemNo()))
                .filter(item -> StringUtils.isEmpty(item.getAsNo()))
                .map(item -> item.getPoCode() + "_" + item.getPoItemNo())  // 新增的map操作
                .distinct()  // 关键去重操作
                .collect(Collectors.toList());
    }

    @Override
    public PageView paaOrderFilterAmountList(PaymentApplyHeadQuery query) {
        BigDecimal taxAmount = query.getTaxAmount();
        //1.查询采购订单明细表中的订单数据-- 条件为供应商代码+公司代码
        List<PurchaseDetailDTO> orderDetails = purchaseOrderClient.getOrderDetailBysupplierCodeAndFactoryCode(query.getSupplierCode(), query.getFactoryCode(), query.getOrderCode());
        List<PurchaseDetailDTO> filteredList = null;
        if (CollectionUtils.isNotEmpty(orderDetails)) {
            //2.拿到数据后到预付款订单明细表中查询订单明细数据(排除作废和删除的数据)，进行分组汇总
            List<String> result = orderDetails.stream()
                    .map(detail -> detail.getOrderCode() + "_" + detail.getOrderRow())
                    .collect(Collectors.toList());
            List<CreatePcaDetailDto> dtolist = paymentAdvanceApplyDetailLogic.findAdvanceApplyDataByDataKey(result);
            //3.拿到页面传过来的申请金额进行比较，只有大于等于的才允许返回前台
            Map<String, BigDecimal> dtoMap = dtolist.stream()
                    .collect(Collectors.toMap(
                            CreatePcaDetailDto::getDataKey,
                            CreatePcaDetailDto::getBudOutMoney
                    ));

            // 4.计算公式：订单行含税金额 - 订单行预付已请款金额(排除OA审批作废和删除的预付款申请，行上的本次请款金额） >= 本次转单金额
            filteredList = orderDetails.stream()
                    .filter(detail -> {
                        String dataKey = detail.getOrderCode() + "_" + detail.getOrderRow();
                        if (dtoMap.containsKey(dataKey)) {
                            BigDecimal taxAmountValue = detail.getTaxAmount();
                            BigDecimal amountToSubtract = dtoMap.get(dataKey);
                            BigDecimal resultAmount = taxAmountValue.subtract(amountToSubtract);
                            return resultAmount.compareTo(taxAmount) >= 0; // 保留 >=2 的数据
                        }
                        return true; // 如果 dtolist 没有匹配的 dataKey，则保留
                    }).collect(Collectors.toList());
        }
        filteredList.removeIf(detail ->
                (detail.getOrderCode() + "_" + detail.getOrderRow()).equals(query.getPoCode() + "_" + query.getPoItemNo())
        );
        return PageUtil.getPV(filteredList, filteredList.size());
    }

    public boolean isValidCurrency(String value) {
        try {
            new BigDecimal(value);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void sendEmailCollection(Long id) {
        PaymentAdvanceApply paymentCodApply = paymentAdvanceApplyService.getById(id);
        //如果状态不为新建不允许发布
        if (paymentCodApply.getStatus()!=7){
            throw new DaoException("只有待付款状态的单据才能汇票催收");
        }
        if (!paymentCodApply.getPaymentWayCode().equals("C")){
            throw new DaoException("付款方式只有承兑汇票的单据才能汇票催收");
        }

        Set<String> emailList = new HashSet<>();
        UserDTO userDTO = userClient.getByUserId(paymentCodApply.getCreateUserId());
        if (ObjectUtil.isNotEmpty(userDTO)&&StringUtils.isNotEmpty(userDTO.getEmail())){
            emailList.add(userDTO.getEmail());
        }
        //1，财务驳回发票交接，增加邮件提醒，  邮件收件人：供应商（(4)财务人员、(12)业务接口人、(5)业务经理）、对账采购组窗口
        SupplierContactsDTO emailBis = supplierClient.getDefaultContact(paymentCodApply.getSupplierCode(), "12");
        SupplierContactsDTO emailFin = supplierClient.getDefaultContact(paymentCodApply.getSupplierCode(), "4");
        SupplierContactsDTO emailJl = supplierClient.getDefaultContact(paymentCodApply.getSupplierCode(), "5");
        if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
            emailList.add(emailBis.getEmail());
        }
        if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
            emailList.add(emailFin.getEmail());
        }
        if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
            emailList.add(emailJl.getEmail());
        }
        if (CollUtil.isNotEmpty(emailList)){
            for (String mapKey : emailList){
                final EmailTmpSingleSendDTO emailTxtSingleSendDTO = new EmailTmpSingleSendDTO();
                emailTxtSingleSendDTO.setTemplateCode("JW_POST_200");
                Map<String, Object> params = Maps.newHashMap();
                CompanyDTO companyDTO = companyClient.getByCode(paymentCodApply.getCompanyCode());
                paymentCodApply.setCompanyName(companyDTO.getCompanyName());
                params.put("data",paymentCodApply);
                params.put("createTime", DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
                emailTxtSingleSendDTO.setParams(params);
                emailTxtSingleSendDTO.setReceiver(mapKey);
                emailTxtSingleSendDTO.setSender(LoginUtil.getUserId());
                emailSendClient.async(emailTxtSingleSendDTO);
            }
            paymentCodApply.setSendEmailCollectionFlag(1);
            paymentAdvanceApplyService.updateById(paymentCodApply);
        }else {
            throw new DaoException("未找到可发送的邮箱，请检查创建人和供应商是否配置邮箱");
        }
    }

    /**
     * 设置确认日志
     * @param paymentId 付款ID
     * @param paymentNo 付款编号
     */
    private void setConfirmLog(List<FinPaymentConfirmLog> logDetailList, Long paymentId, String paymentNo) {
        for (FinPaymentConfirmLog log : logDetailList) {
            log.setPaymentId(paymentId);
            log.setPaymentNo(paymentNo);
            log.setWarnCode("WARN");
            log.setUserId(LoginUtil.getUserId());
            log.setUserName(LoginUtil.getName());
            log.setCreatedTime(LocalDateTime.now());
        }
        finPaymentConfirmLogService.saveOrUpdateBatch(logDetailList);
    }
}
