package com.jwipc.finance.logic.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
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.fastjson2.JSONArray;
import com.baomidou.dynamic.datasource.annotation.DS;
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.api.dto.ErpApiResult;
import com.jwipc.api.dto.ErpApiResult1;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.constant.PaymentOaClient;
import com.jwipc.finance.convert.AccountStatementDetailConvert;
import com.jwipc.finance.convert.InvoicedApplyAttachmentConvert;
import com.jwipc.finance.convert.InvoicedApplyConvert;
import com.jwipc.finance.convert.InvoicedReceiptConvert;
import com.jwipc.finance.dto.*;
import com.jwipc.finance.entity.*;
import com.jwipc.finance.logic.*;
import com.jwipc.finance.model.po.CreatePcaDetailPO;
import com.jwipc.finance.model.po.InvoicedApplyItemPO;
import com.jwipc.finance.model.po.InvoicedApplyPO;
import com.jwipc.finance.model.po.InvoicedApplyPrintPO;
import com.jwipc.finance.model.query.InvoicedApplyQuery;
import com.jwipc.finance.model.query.PaymentApplyItemQuery;
import com.jwipc.finance.service.*;
import com.jwipc.order.client.PurchaseOrderClient;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.prop.SysProp;
import com.jwipc.security.LoginUtil;
import com.jwipc.security.dto.CurrentUserDTO;
import com.jwipc.supplier.clent.dto.SupplierContactsDTO;
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.DigitalSealBusinessDetailDTO;
import com.jwipc.sys.dto.KingdeeInvoiceCloudImageDTO;
import com.jwipc.sys.entity.Attachment;
import com.jwipc.sys.entity.BusinessAttachment;
import com.jwipc.sys.entity.DigitalSealBusinessDetail;
import com.jwipc.sys.logic.BusinessAttachmentLogic;
import com.jwipc.sys.logic.ESignLogic;
import com.jwipc.sys.logic.KingdeeImageLogic;
import com.jwipc.sys.logic.KingdeeInvoiceCloudLogic;
import com.jwipc.sys.service.IAttachmentService;
import com.jwipc.sys.service.IBusinessAttachmentService;
import com.jwipc.sys.service.IDigitalSealBusinessDetailService;
import com.jwipc.sys.util.FinancialShareUtil;
import com.jwipc.util.DateUtils;
import com.jwipc.util.EasyExcelUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.baomidou.dynamic.datasource.support.DdConstants.SLAVE;

/**
 * @author shenyang.ou
 * @date 2024/3/5 11:18
 * @desc
 */
@Service
@RequiredArgsConstructor
@DS(SLAVE)
public class InvoicedApplyLogicImpl implements InvoicedApplyLogic {
    private static final Logger LOGGER = LoggerFactory.getLogger(InvoicedApplyLogicImpl.class);
    private final IInvoicedApplyService invoicedApplyService;
    private final IDeductionService deductionService;
    private final PurchaseOrderClient purchaseOrderClient;
    private final IAttachmentManualCheckService attachmentManualCheckService;
    private final DictClient dictClient;
    private final ESignLogic eSignLogic;
    private final IInvoicedApplyApproveService invoicedApplyApproveService;
    private final IInvoicedApplyDetailService invoicedApplyDetailService;
    private final IInvoicedApplyPostResultService invoicedApplyPostResultService;
    private final IPayableRefundService payableRefundService;
    private final InvoicedApplyDetailLogic invoicedApplyDetailLogic;
    private final ReceiptVoucherLogic receiptVoucherLogic;
    private final AccountStatementLogic accountStatementLogic;
    private final AccountStatementDetailConvert accountStatementDetailConvert;
    private final InvoicedApplyAttachmentConvert invoicedApplyAttachmentConvert;
    private final IInvoicedApplyAttachmentService invoicedApplyAttachmentService;
    private final IDigitalSealBusinessDetailService digitalSealBusinessDetailService;
    private final IAttachmentService attachmentService;
    private final IBusinessAttachmentService businessAttachmentService;
    private final FileClient fileClient;
    private final KingdeeImageLogic kingdeeImageLogic;
    //    private final InvoicedApplyAttachmentLogic invoicedApplyAttachmentLogic;
    private final AccountStatementDetailLogic accountStatementDetailLogic;
    private final TaxClient taxClient;
    private final CompanyClient companyClient;
    private final IInvoicedReceiptService invoicedReceiptService;
    private final KingdeeInvoiceCloudLogic kingdeeInvoiceCloudLogic;
    private final InvoicedReceiptConvert invoicedReceiptConvert;
    private final IInvoicedApplyPaService invoicedApplyPaService;
    private final IPaymentAdvanceApplyDetailService paymentAdvanceApplyDetailService;
    private final InvoicedApplyPaLogic invoicedApplyPaLogic;
    private final InvoicedApplyOptLogic invoicedApplyOptLogic;
    private final InvoicedReceiptLogic invoicedReceiptLogic;
    private final IFinPaymentConfirmLogService finPaymentConfirmLogService;
    private final InvoicedApplyApproveLogic invoicedApplyApproveLogic;
    private final InvoicedApplyConvert invoicedApplyConvert;
    private final SequenceClient sequenceClient;
    private final ESignClient eSignClient;
    private final SupplierClient supplierClient;
    private final EmailSendClient emailSendClient;
    private final PaymentAdvanceApplyDetailLogic paymentAdvanceApplyDetailLogic;
    private final SysProp sysProp;
    private final BusinessAttachmentLogic businessAttachmentLogic;
    private final PaymentOaClient paymentOaClient;
    private final FinancialShareUtil financialShareUtil;

    @Override
    public InvoicedApplyDTO getById(Long id) {
        InvoicedApply invoicedApply = invoicedApplyService.getById(id);
        return invoicedApplyConvert.entity2DTO(invoicedApply);
    }

    @Override
    public InvoicedApplyDTO getByInvoiceApplyNo(String invoiceApplyNo) {
        InvoicedApply invoicedApply = invoicedApplyService.getOne(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getInvoiceApplyNo, invoiceApplyNo).last(" limit 1"));
        return invoicedApplyConvert.entity2DTO(invoicedApply);
    }

    /**
     * 暂时存表头
     * fin/invoiced/apply/rest/saveHead
     *
     * @param params 请求参数
     */
    @Override
    @Transactional
    public void updateHead(InvoicedApplySaveParamDTO params) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("开票申请表头数据异常, 请重新操作");
        }
        // 变更的开票申请表头数据
        InvoicedApplyDTO head = params.getHeadData();
        final InvoicedApply oldHead = invoicedApplyService.getById(head.getId());
        if (1 != oldHead.getStatus() && 3 != oldHead.getStatus() && 8 != oldHead.getStatus()) {
            throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
        }

        if (!invoicedApplyService.updateById(invoicedApplyConvert.dto2Entity(head))) {
            throw new DaoException("数据保存失败, 请联系管理员");
        }
        // 附件关系
        businessAttachmentService.remove(Wrappers.lambdaQuery(BusinessAttachment.class).eq(BusinessAttachment::getBusinessId, head.getId()));
        List<BusinessAttachmentDTO> businessAttachmentDTOList = params.getBusinessAttachmentDTOList();
        businessAttachmentDTOList.forEach(item -> {
            item.setBusinessTypeCode("invoice_apply");
            item.setId(null);
            item.setDeleteFlag(0);
            item.setBusinessId(head.getId());
        });
        businessAttachmentLogic.saveAttachment(businessAttachmentDTOList);
        // 对接乐税系统，关联或取消关联发票
        invoicedReceiptLogic.operateInvoice(params.getInvoicedReceiptData(), head.getId(), LoginUtil.getCurrentUser());
    }

    /**
     * 暂时数据
     *
     * @param params 请求参数
     */
    @Override
    @Transactional
    public void dataSave(InvoicedApplySaveParamDTO params, List<InvoicedApplyItemPO> inquiryPOS) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("开票申请表头数据异常, 请重新操作");
        }
//        if (CollectionUtils.isEmpty(params.getDetailDate())) {
//            throw new DaoException("新增的明细数据异常, 请重新操作");
//        }

        InvoicedApplyDTO headDto = params.getHeadData();
        InvoicedApply head = invoicedApplyConvert.dto2Entity(headDto);
        if (head.getId() == null) {
            head.setInvoiceApplyNo(sequenceClient.getCodeSequenceNo("invoiced_apply_code", 6));
            head.setId(null);
            head.setCreateTime(LocalDateTime.now());
            head.setCreateUserId(LoginUtil.getUserId());
            head.setCreateUserCode(LoginUtil.getAccount());
            head.setCreateUserName(LoginUtil.getName());
            if (!invoicedApplyService.save(head)) {
                throw new DaoException("保存开票申请表头数据失败, 前联系管理员");
            }
//            if (CollectionUtils.isNotEmpty(params.getBusinessAttachmentDTOList())) {
//                List<BusinessAttachmentDTO> insertList = Lists.newArrayList();
//                // 新建时，如果有上传附件的场景
//                for (BusinessAttachmentDTO businessAttachment : params.getBusinessAttachmentDTOList()) {
//                    if (!Objects.isNull(businessAttachment.getId())) {
//                        businessAttachment.setId(null);
//                    }
//                    // 初始化值
//                    businessAttachment.setRemark(null);
//                    businessAttachment.setDeleteFlag(Integer.valueOf(0));
//                    businessAttachment.setImageCode(null);
//                    businessAttachment.setImagePath(null);
//                    // id 统一使用开票申请单的id
//                    businessAttachment.setBusinessId(head.getId());
//                    businessAttachment.setBusinessTypeCode("invoice_apply");
//                    if (Objects.isNull(businessAttachment.getBusinessCode())) {
//                        // 新上传直接用开票申请单的编号
//                        businessAttachment.setBusinessCode(head.getInvoiceApplyNo());
//                    } else {
//                        // 从对账单过来的继续沿用
//                        businessAttachment.setBusinessCode(businessAttachment.getBusinessCode());
//                    }
//                    insertList.add(businessAttachment);
//                }
//                businessAttachmentLogic.saveAttachment(insertList);
//            }
        } else {
            head.setUpdateTime(LocalDateTime.now());
            head.setUpdateUserId(LoginUtil.getUserId());
            head.setUpdateUserCode(LoginUtil.getAccount());
            head.setUpdateUserName(LoginUtil.getName());
            if (!invoicedApplyService.updateById(head)) {
                throw new DaoException("保存开票申请表头数据失败, 前联系管理员");
            }
            InvoicedApply old = invoicedApplyService.getById(head.getId());
            //取消完成标识
//            accountStatementLogic.updateInvoiceCompleteFlagByAsId(old.getAccountStatementId(),0);
            invoicedApplyDetailService.remove(Wrappers.lambdaQuery(InvoicedApplyDetail.class).eq(InvoicedApplyDetail::getIaId, head.getId()));
        }

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


//        List<BusinessAttachmentDTO> businessAttachmentDTOList = params.getBusinessAttachmentDTOList();
//        if (CollUtil.isNotEmpty(businessAttachmentDTOList)){
//            List<InvoicedApplyAttachment> insetInvoicedApplyAttachmentList = Lists.newArrayList();
//            // businessAttachmentDTOList中过滤出id为空的数据list
//            businessAttachmentDTOList = businessAttachmentDTOList.stream().filter(item -> item.getId() == null).toList();
//            for (InvoicedApplyAttachmentDTO invoicedApplyAttachmentDTO : businessAttachmentDTOList) {
//                InvoicedApplyAttachment invoicedApplyAttachment = invoicedApplyAttachmentConvert.dto2Entity(invoicedApplyAttachmentDTO);
//                invoicedApplyAttachment.setIaId(head.getId());
//                invoicedApplyAttachment.setCreateTime(LocalDateTime.now());
//                invoicedApplyAttachment.setCreateUser(LoginUtil.getUserId());
//                invoicedApplyAttachment.setFileType(0);
//                insetInvoicedApplyAttachmentList.add(invoicedApplyAttachment);
//            }
//            if (CollUtil.isNotEmpty(insetInvoicedApplyAttachmentList)){
//                invoicedApplyAttachmentService.saveBatch(insetInvoicedApplyAttachmentList);
//            }
//        }else {
//            //取出siList中的poCode
//            List<String> poCodeList = inquiryPOS.stream().map(InvoicedApplyItemPO::getPoCode).distinct().toList();
//            InvoicedApplyAttachmentQuery query = new InvoicedApplyAttachmentQuery();
//            query.setIaId(head.getId());
//            query.setReloadFlag(1);
//            //poCodeList逗号隔开
//            query.setBusinessCodes(String.join(",", poCodeList));
//            query.setBusinessTypeCodes("purchase_order");
//
//            PageView pageView = invoicedApplyAttachmentLogic.list(query);
//            if (CollUtil.isNotEmpty(pageView.getRows())){
//                List<InvoicedApplyAttachment> saveList = new ArrayList<>();
//                List<InvoicedApplyAttachmentDTO> attachmentDTOList = (List<InvoicedApplyAttachmentDTO>) pageView.getRows();
//                attachmentDTOList.forEach(item -> {
//                    InvoicedApplyAttachment accountStatementAttachment =  new InvoicedApplyAttachment();
//                    accountStatementAttachment.setBusinessAttachmentId(item.getId());
//                    accountStatementAttachment.setIaId(head.getId());
//                    accountStatementAttachment.setFileId(item.getFileId());
//                    accountStatementAttachment.setCreateTime(LocalDateTime.now());
//                    accountStatementAttachment.setCreateUser(LoginUtil.getUserId());
//                    accountStatementAttachment.setFileType(0);
//                    saveList.add(accountStatementAttachment);
//                });
//                invoicedApplyAttachmentService.saveBatch(saveList);
//            }
//        }
//
//        //保存签署附件
//        List<InvoicedApplyAttachmentDTO> signAttachmentDTOList = params.getSignAttachmentDTOList();
//        if (CollUtil.isNotEmpty(signAttachmentDTOList)){
//            List<InvoicedApplyAttachment> invoicedApplyAttachments = invoicedApplyAttachmentService.list(new LambdaQueryWrapper<InvoicedApplyAttachment>()
//                    .eq(InvoicedApplyAttachment::getIaId,head.getId()).eq(InvoicedApplyAttachment::getFileType,1).eq(InvoicedApplyAttachment::getDeleteFlag,0));
//            if (CollUtil.isNotEmpty(invoicedApplyAttachments)){
//                signAttachmentDTOList.forEach(signAttachmentDTO -> {
//                    invoicedApplyAttachments.forEach(invoicedApplyAttachmentDTO -> {
//                        if (invoicedApplyAttachmentDTO.getFileId().equals(signAttachmentDTO.getFileId())){
//                            signAttachmentDTO.setId(invoicedApplyAttachmentDTO.getId());
//                        }
//                    });
//                });
//            }
//            signAttachmentDTOList = signAttachmentDTOList.stream().filter(item -> item.getId() == null).toList();
//            List<InvoicedApplyAttachment> insetInvoicedApplyAttachmentList = Lists.newArrayList();
//            for (InvoicedApplyAttachmentDTO invoicedApplyAttachmentDTO : signAttachmentDTOList) {
//                InvoicedApplyAttachment invoicedApplyAttachment = invoicedApplyAttachmentConvert.dto2Entity(invoicedApplyAttachmentDTO);
//                invoicedApplyAttachment.setIaId(head.getId());
//                invoicedApplyAttachment.setCreateTime(LocalDateTime.now());
//                invoicedApplyAttachment.setCreateUser(LoginUtil.getUserId());
//                invoicedApplyAttachment.setFileType(1);
//                insetInvoicedApplyAttachmentList.add(invoicedApplyAttachment);
//            }
//            if (CollUtil.isNotEmpty(insetInvoicedApplyAttachmentList)){
//                invoicedApplyAttachmentService.saveBatch(insetInvoicedApplyAttachmentList);
//            }
//        }

//        List<InvoicedApplyItemDTO> detailList = params.getDetailDate();

//        CreateInvoicedApplyPageQuery query = new CreateInvoicedApplyPageQuery();
//        query.setFactoryCode(head.getFactoryCode());
//        query.setAsId(head.getAccountStatementId());
        //分库分表查询不生效，需要把这个方法提到外面先行查询，邓京术 2025-06-29
//        List<InvoicedApplyItemPO> inquiryPOS = accountStatementDetailService.provideCreateInvoicedApplyPage(null, query);
        List<InvoicedApplyItemDTO> detailList = accountStatementDetailConvert.invoicedApplyItemPO2DTOList(inquiryPOS);
        for (InvoicedApplyItemDTO invoicedApplyItemDTO : detailList) {
            invoicedApplyItemDTO.setTaxCode(invoicedApplyItemDTO.getAsTaxCode());
            invoicedApplyItemDTO.setTaxValue(invoicedApplyItemDTO.getAsTaxValue());
            invoicedApplyItemDTO.setNotTaxPrice(invoicedApplyItemDTO.getAsNotTaxPrice());
            invoicedApplyItemDTO.setTaxPrice(invoicedApplyItemDTO.getAsTaxPrice());
            invoicedApplyItemDTO.setNotTaxAmount(invoicedApplyItemDTO.getAsNotTaxAmount());
            invoicedApplyItemDTO.setTaxAmount(invoicedApplyItemDTO.getAsTaxAmount());
            invoicedApplyItemDTO.setDiffTaxAmount(invoicedApplyItemDTO.getAsDiffTaxAmount());
        }
        List<InvoicedApplyDetail> iadList = Lists.newArrayList();
        int i = 1;
        for (InvoicedApplyItemDTO dto : detailList) {
            InvoicedApplyDetail iad = dto.toIad();
            //判断对账明细中是否存在已经使用过的物料凭证
//            InvoicedApplyDetail detail = invoicedApplyDetailService.getOne(Wrappers.lambdaQuery(InvoicedApplyDetail.class).eq(InvoicedApplyDetail::getAsdId,iad.getAsdId()).eq(InvoicedApplyDetail::getDeleteFlag,0).last(" limit 1"));
//            if (ObjectUtil.isNotNull(detail)){
//                throw new DaoException("对账单号："+detail.getAsNo()+",已创建过开票申请单，无法继续创建");
//            }
            iad.setIaId(head.getId());
            iad.setIaNo(head.getInvoiceApplyNo());
            iad.setId(null);
            iad.setCreateTime(LocalDateTime.now());
            iad.setCreateUserId(LoginUtil.getUserId());
            iad.setCreateUserCode(LoginUtil.getAccount());
            iad.setCreateUserName(LoginUtil.getName());
            iad.setItemNo(StringUtils.leftPad(String.valueOf(i * 10), 6, "0"));
            iadList.add(iad);
            i++;
        }

        // 校验开票明细中反向凭证对应的正向是否也在其中
        final String checkResult = this.checkInvoicedApplyDetail(head.getSupplierCode(), iadList, head.getOrderType());
        if (StringUtils.isNotEmpty(checkResult)) {
            throw new DaoException(checkResult);
        }

        // 保存开票申请明细数据
//        if (CollectionUtils.isNotEmpty(iadList)) {
//            if (!this.invoicedApplyDetailService.saveBatch(iadList)) {
//                throw new DaoException("保存开票申请明细数据失败, 前联系管理员");
//            }
//        }

        // 保存开票申请单的返利和扣款信息
//        this.addSdAndSr(head, sdIdList, srIdList);
//        this.addPa(head, params.getAddPaIds());

        // 更新对账单及明细的开票完成标识
//        List<Long> asdIdList = Lists.newArrayList();
//        for (InvoicedApplyDetail detail : iadList) {
//            asdIdList.add(detail.getAsdId());
//        }
//        accountStatementLogic.updateInvoiceCompleteFlag(asdIdList, 1);
        accountStatementLogic.updateInvoiceCompleteFlagByAsId(head.getAccountStatementId(), 1);

        invoicedApplyOptLogic.addContentRecord(1, null, head, Lists.newArrayList(), Lists.newArrayList(), LoginUtil.getCurrentUser());

        // 对接乐税系统，关联或取消关联发票
        invoicedReceiptLogic.operateInvoice(params.getInvoicedReceiptData(), head.getId(), LoginUtil.getCurrentUser());

    }

    @Override
    @Transactional
    public void redReversalSave(InvoicedApplySaveParamDTO params) {

        List<InvoicedReceiptDTO> invoicedReceiptDataList = params.getInvoicedReceiptData();
        if (CollUtil.isNotEmpty(invoicedReceiptDataList)) {
            //过滤出invoicedReceiptDataList中notDeleteFlag为0的数据
            invoicedReceiptDataList = invoicedReceiptDataList.stream().filter(invoicedReceiptDTO -> invoicedReceiptDTO.getNotDeleteFlag() == 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(invoicedReceiptDataList)) {
                InvoicedApplyDTO headDto = params.getHeadData();
                InvoicedApply old = invoicedApplyService.getById(headDto.getId());
                if (old.getRedReversalStatus() != 1 && old.getRedReversalStatus() != 4) {
                    throw new DaoException("该开票申请单不支持补票操作, 请检查");
                }
                InvoicedApply head = invoicedApplyConvert.dto2Entity(headDto);
                head.setUpdateTime(LocalDateTime.now());
                head.setUpdateUserId(LoginUtil.getUserId());
                head.setUpdateUserCode(LoginUtil.getAccount());
                head.setUpdateUserName(LoginUtil.getName());
                head.setRedReversalStatus(2);
                if (!invoicedApplyService.updateById(head)) {
                    throw new DaoException("保存开票申请表头数据失败, 前联系管理员");
                }

                invoicedReceiptDataList.forEach(e -> e.setIaId(head.getId()));

                //判断本次发票号码是否重复
                List<InvoicedReceiptDTO> nonNullNameList = invoicedReceiptDataList.stream()
                        .filter(p -> StringUtils.isNotEmpty(p.getInvoiceNumber()))
                        .toList();
                if (CollectionUtils.isNotEmpty(nonNullNameList)) {
                    Map<String, List<InvoicedReceiptDTO>> ext = nonNullNameList.stream()
                            .collect(Collectors.groupingBy(InvoicedReceiptDTO::getInvoiceNumber))
                            .entrySet().stream()
                            .filter(entry -> entry.getValue().size() > 1)
                            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                    if (ObjectUtil.isNotNull(ext)) {
                        ext.forEach((key, value) -> {
                            throw new DaoException("发票号码：" + key + "重复" + value.size() + "条，请删除其中" + (value.size() - 1) + "条");
                        });
                    }
                }
                //判断本次数电发票号码是否重复
                List<InvoicedReceiptDTO> nonNullElectronNameList = params.getInvoicedReceiptData().stream()
                        .filter(p -> StringUtils.isNotEmpty(p.getElectronInvoiceNumber()))
                        .toList();
                if (CollectionUtils.isNotEmpty(nonNullElectronNameList)) {
                    Map<String, List<InvoicedReceiptDTO>> electronExt = nonNullElectronNameList.stream()
                            .collect(Collectors.groupingBy(InvoicedReceiptDTO::getElectronInvoiceNumber))
                            .entrySet().stream()
                            .filter(entry -> entry.getValue().size() > 1)
                            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                    if (ObjectUtil.isNotNull(electronExt)) {
                        electronExt.forEach((key, value) -> {
                            throw new DaoException("数电发票号码：" + key + "重复" + value.size() + "条，请删除其中" + (value.size() - 1) + "条");
                        });
                    }
                }
                //判断发票号码是否重复
                for (InvoicedReceiptDTO invoicedReceipt : invoicedReceiptDataList) {
                    if (StrUtil.isNotEmpty(invoicedReceipt.getInvoiceNumber())) {
                        InvoicedReceipt invoicedReceipt1 = invoicedReceiptService.getExitDataByIaIdAndInvoiceNumber(head.getId(), invoicedReceipt.getInvoiceNumber());
                        if (ObjectUtil.isNotNull(invoicedReceipt1)) {
                            throw new DaoException("发票号码：" + invoicedReceipt.getInvoiceNumber() + "在系统中已存在，不可录入");
                        }
                    }

                }
                //判断数电发票号码是否重复
                for (InvoicedReceiptDTO invoicedReceipt : invoicedReceiptDataList) {
                    invoicedReceipt.setDeleteFlag(0);
                    if (StrUtil.isNotEmpty(invoicedReceipt.getElectronInvoiceNumber())) {
                        invoicedReceipt.setElectronInvoiceNumber(invoicedReceipt.getElectronInvoiceNumber().trim());//去除空格
                        InvoicedReceipt invoicedReceipt1 = invoicedReceiptService.getExitDataByIaIdAndElectronInvoiceNumber(head.getId(), invoicedReceipt.getElectronInvoiceNumber());
                        if (ObjectUtil.isNotNull(invoicedReceipt1)) {
                            throw new DaoException("数电发票号码：" + invoicedReceipt.getElectronInvoiceNumber() + "在系统中已存在，不可录入");
                        }
                    }
                }
                // 新增或编辑
                invoicedReceiptService.saveOrUpdateBatch(invoicedReceiptConvert.dto2EntityList(invoicedReceiptDataList));
                this.toImg(headDto.getId());
                this.toAllImg(headDto.getId());
            }
        }
    }

    /**
     * 编辑数据
     *
     * @param params 请求参数
     */
    @Override
    @Transactional
    public void dataEdit(InvoicedApplySaveParamDTO params, List<InvoicedApplyItemPO> inquiryPOS) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("修改的表头数据异常, 请重新操作");
        }
//        if (CollectionUtils.isEmpty(params.getDetailDate())) {
//            throw new DaoException("修改的明细数据异常, 请重新操作");
//        }
        InvoicedApplyDTO headDto = params.getHeadData();
        InvoicedApply head = invoicedApplyConvert.dto2Entity(headDto);
        final InvoicedApply oldHead = invoicedApplyService.getById(head.getId());
        if (1 != oldHead.getStatus() && 3 != oldHead.getStatus()) {
            throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
        }

        head.setUpdateTime(LocalDateTime.now());
        head.setUpdateUserId(LoginUtil.getUserId());
        head.setUpdateUserCode(LoginUtil.getAccount());
        head.setUpdateUserName(LoginUtil.getName());
        if (!invoicedApplyService.updateById(head)) {
            throw new DaoException("保存开票申请表头数据失败, 前联系管理员");
        }

        // 开票申请单采购确认出现总金额差异超过±1 则需要推送OA审批
        BigDecimal diffAmount = BigDecimal.ZERO;
//        List<InvoicedApplyItemDTO> detailList = params.getDetailDate();

//        CreateInvoicedApplyPageQuery query = new CreateInvoicedApplyPageQuery();
//        query.setFactoryCode(head.getFactoryCode());
//        query.setAsId(head.getAccountStatementId());
        //分库分表查询不生效，需要把这个方法提到外面先行查询，邓京术 2025-06-29
//        List<InvoicedApplyItemPO> inquiryPOS = accountStatementDetailService.provideCreateInvoicedApplyPage(null, query);
        List<InvoicedApplyItemDTO> detailList = accountStatementDetailConvert.invoicedApplyItemPO2DTOList(inquiryPOS);
        for (InvoicedApplyItemDTO invoicedApplyItemDTO : detailList) {
            invoicedApplyItemDTO.setTaxCode(invoicedApplyItemDTO.getAsTaxCode());
            invoicedApplyItemDTO.setTaxValue(invoicedApplyItemDTO.getAsTaxValue());
            invoicedApplyItemDTO.setNotTaxPrice(invoicedApplyItemDTO.getAsNotTaxPrice());
            invoicedApplyItemDTO.setTaxPrice(invoicedApplyItemDTO.getAsTaxPrice());
            invoicedApplyItemDTO.setNotTaxAmount(invoicedApplyItemDTO.getAsNotTaxAmount());
            invoicedApplyItemDTO.setTaxAmount(invoicedApplyItemDTO.getAsTaxAmount());
            invoicedApplyItemDTO.setDiffTaxAmount(invoicedApplyItemDTO.getAsDiffTaxAmount());
        }

        List<InvoicedApplyDetail> iadList = Lists.newArrayList();
        for (InvoicedApplyItemDTO dto : detailList) {
            InvoicedApplyDetail iad = dto.toIad();
            if (0 == dto.getId()) {
                iad.setCreateUserId(LoginUtil.getUserId());
                iad.setCreateUserCode(LoginUtil.getAccount());
                iad.setCreateUserName(LoginUtil.getName());
                iad.setCreateTime(LocalDateTime.now());
                iad.setId(null);
            } else {
                iad.setUpdateUserId(LoginUtil.getUserId());
                iad.setUpdateUserCode(LoginUtil.getAccount());
                iad.setUpdateUserName(LoginUtil.getName());
                iad.setUpdateTime(LocalDateTime.now());
            }

            diffAmount = dto.getIaDiffAmount().add(diffAmount);
            iadList.add(iad);
        }


        // 校验开票明细中反向凭证对应的正向是否也在其中
        final String checkResult = this.checkInvoicedApplyDetail(head.getSupplierCode(), iadList, head.getOrderType());
        if (StringUtils.isNotEmpty(checkResult)) {
            throw new DaoException(checkResult);
        }

        if (CollectionUtils.isNotEmpty(iadList)) {
            if (!invoicedApplyDetailService.saveOrUpdateBatch(iadList)) {
                throw new DaoException("保存开票申请明细数据失败, 请联系管理员");
            }
        }

        if (CollectionUtils.isNotEmpty(params.getDelDetailIds())) {
            List<InvoicedApplyDetail> delDetailList = Lists.newArrayList();
            for (Long did : params.getDelDetailIds()) {
                InvoicedApplyDetail iad = new InvoicedApplyDetail();
                iad.setId(did);
                iad.setDeleteFlag(1);
                iad.setItemNo("000000");
                iad.setUpdateUserId(LoginUtil.getUserId());
                iad.setUpdateUserCode(LoginUtil.getAccount());
                iad.setUpdateUserName(LoginUtil.getName());
                iad.setUpdateTime(LocalDateTime.now());
                delDetailList.add(iad);
            }
            if (!invoicedApplyDetailService.updateBatchById(delDetailList)) {
                throw new DaoException("删除开票申请明细数据失败, 前联系管理员");
            }
        }

        // 删除开票申请对应的扣款和返利记录
//        this.delSdAndSr(delSdIdList, delSrIdList);
//        this.delPa(head,addPaIds);

        // 添加开票申请对应的扣款和返利
//        this.addSdAndSr(head, addSdIdList, addSrIdList);
//        this.addPa(head, addPaIds);

        // 开票完成
        List<Long> asdIdList1 = Lists.newArrayList();
        for (InvoicedApplyDetail detail : iadList) {
            asdIdList1.add(detail.getAsdId());
        }
        accountStatementLogic.updateInvoiceCompleteFlag(asdIdList1, 1);

        // 开票未完成
        if (CollectionUtils.isNotEmpty(params.getDelDetailIds())) {
            List<InvoicedApplyDetail> delIadList = invoicedApplyDetailService.findByIdList(params.getDelDetailIds());
            List<Long> asdIdList2 = Lists.newArrayList();
            for (InvoicedApplyDetail delIad : delIadList) {
                if (1 == delIad.getDeleteFlag()) {
                    asdIdList2.add(delIad.getAsdId());
                }
            }
            accountStatementLogic.updateInvoiceCompleteFlag(asdIdList2, 0);
        }

        // 重新生成开票明细的行号
        invoicedApplyDetailLogic.updateDetailItemNo(head.getId());
    }


    @Override
    public PageView selectDataByQuery(InvoicedApplyQuery query) {
        //已经删除的不查询 2024-08-26 邓京术
        query.setDelFlg(0);
        final Page<InvoicedApply> dbPage = PageUtil.toPage(query);
        List<InvoicedApplyPO> invoicedApplyPOS = invoicedApplyService.selectDataByQuery(dbPage, query);
        List<InvoicedApplyDTO> invoicedApplyDTOS = invoicedApplyConvert.po2PageListDTO(invoicedApplyPOS);
        return PageUtil.getPV(invoicedApplyDTOS, dbPage.getTotal());
    }

    @Override
    public List<InvoicedApplyDTO> listAll(InvoicedApplyQuery query) {
        //已经删除的不查询 2024-08-26 邓京术
        query.setDelFlg(0);
        List<InvoicedApplyPO> invoicedApplyPOS = invoicedApplyService.selectDataByQuery(null, query);
        return invoicedApplyConvert.po2PageListDTO(invoicedApplyPOS);
    }

    /**
     * 开票申请单删除
     *
     * @param ids 开票申请ID
     */
    @Override
    @Transactional
    public void dataDel(String ids, Boolean logicDelete) {
        if (StringUtils.isEmpty(ids)) {
            throw new DaoException("参数异常, 请重新操作");
        }
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        List<InvoicedApply> applyList = Lists.newArrayList();

        InvoicedApplyQuery query = new InvoicedApplyQuery();
        query.setIaIdList(idList);
        final List<InvoicedApplyPO> list = invoicedApplyService.selectDataByQuery(null, query);

        boolean exceptionFlag = false;
        for (InvoicedApplyPO ia : list) {
            InvoicedApply updateIa = new InvoicedApply();
            updateIa.setId(ia.getId());
            updateIa.setDeleteFlag(1);
            updateIa.setUpdateUserId(StpUtil.isLogin() ? LoginUtil.getUserId() : 1L);
            updateIa.setUpdateUserCode(StpUtil.isLogin() ? LoginUtil.getAccount() : "admin");
            updateIa.setUpdateUserName(StpUtil.isLogin() ? LoginUtil.getName() : "admin");
            updateIa.setUpdateTime(LocalDateTime.now());

            // 1:暂存 2:待采购确认 3:采购拒绝 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认 8:财务拒绝 9:确认完成
            if ("1,3,8".contains(ia.getStatus().toString()) ||
                    (9 == ia.getStatus() && ("3,4,5".contains(ia.getPostStatus().toString())))) {
                applyList.add(updateIa);
            } else {
                exceptionFlag = true;
            }

            accountStatementLogic.updateInvoiceCompleteFlagByAsId(ia.getAccountStatementId(), 0);


            PayableDeleteDTO payImportToOpenDTO = new PayableDeleteDTO();
            payImportToOpenDTO.setBillno(ia.getAccountStatementNo());
            if (StrUtil.isEmpty(ia.getFinancePayablePostId())){
                continue;
            }
            //提交到共享
            String accessToken = financialShareUtil.getShareAccessToken();
            ErpApiResult1<PayImportToOpenResultDTO> result = paymentOaClient.payableDelete(accessToken,payImportToOpenDTO);
            if (!result.getStatus()) {
                throw new DaoException("共享系统接口报错：" + result.getMessage());
            }
        }

        if (exceptionFlag) {
            throw new DaoException("选中的开票申请存在数据状态不支持删除操作, 请检查");
        }

        if (CollectionUtils.isNotEmpty(applyList)) {
            if (!invoicedApplyService.updateBatchById(applyList)) {
                throw new DaoException("删除选中的开票申请失败, 请检查");
            }
        }

        List<InvoicedApplyDetail> updateIadList = Lists.newArrayList();
        final List<InvoicedApplyDetail> iadList = invoicedApplyDetailService.findByInvoiceApplyId(null, idList);
        for (InvoicedApplyDetail iad : iadList) {
            InvoicedApplyDetail updateIad = new InvoicedApplyDetail();
            updateIad.setId(iad.getId());
            updateIad.setDeleteFlag(1);
            updateIad.setUpdateUserId(LoginUtil.getUserId());
            updateIad.setUpdateUserCode(LoginUtil.getAccount());
            updateIad.setUpdateUserName(LoginUtil.getName());
            updateIad.setUpdateTime(LocalDateTime.now());
            updateIadList.add(updateIad);
        }

        if (CollectionUtils.isNotEmpty(updateIadList)) {
            if (!invoicedApplyDetailService.updateBatchById(updateIadList)) {
                throw new DaoException("删除选中的开票申请单对应的明细数据失败, 请检查");
            }
        }


//        // 开票未完成
//        List<Long> asdIdList = Lists.newArrayList();
//        //删除明细id
//        List<Long> detailIds = Lists.newArrayList();
//        for (InvoicedApplyDetail delIad : iadList) {
//            asdIdList.add(delIad.getAsdId());
//            detailIds.add(delIad.getId());
//        }
//        accountStatementLogic.updateInvoiceCompleteFlag(asdIdList, 0);

        for (Long asId : idList) {
//            //释放扣款信息
//            List<AccountStatementDeduction> accountStatementDeductions = accountStatementDeductionService.selectList(new EntityWrapper<AccountStatementDeduction>().eq("as_id", asId));
//            if (CollectionUtils.isNotEmpty(accountStatementDeductions)){
//                accountStatementDeductions.forEach(accountStatementDeduction -> {
//                    accountStatementDeduction.setDeleteFlag(1);
//                    if (accountStatementDeduction.getUseFlag()==1){
//                        DeductionManage deductionManage = new DeductionManage();
//                        deductionManage.setId(accountStatementDeduction.getDeductionId());
//                        deductionManage.setStatementOrderCode("");
//                        deductionManage.setWhether(0);
//                        deductionManageService.updateById(deductionManage);
//                    }
//                });
//                accountStatementDeductionService.updateBatchById(accountStatementDeductions);
//            }
            //释放发票信息
            List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(Wrappers.lambdaQuery(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, asId));
            if (CollectionUtils.isNotEmpty(invoicedReceipts)) {
                if (logicDelete) {
                    invoicedReceipts.forEach(invoicedReceipt -> {
                        invoicedReceipt.setDeleteFlag(1);
                        invoicedReceipt.setUpdateTime(LocalDateTime.now());
                        invoicedReceiptService.updateById(invoicedReceipt);
                    });
                } else {
                    invoicedReceipts.forEach(invoicedReceiptService::removeById);
                }

                //删除发票确认
                List<String> serialNoList = invoicedReceipts.stream()
                        .map(InvoicedReceipt::getSerialNo)
                        .filter(StrUtil::isNotEmpty)
                        .toList();
                if (CollUtil.isNotEmpty(serialNoList)) {
                    kingdeeInvoiceCloudLogic.deleteInvoice(String.join(",", serialNoList));
                }
            }

            //释放预付款信息
            List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, asId));
            if (CollectionUtils.isNotEmpty(invoicedApplyPaList)) {
                if (logicDelete) {
                    invoicedApplyPaList.forEach(invoicedApplyPa -> {
                        invoicedApplyPa.setDeleteFlag(1);
                        invoicedApplyPaService.updateById(invoicedApplyPa);
                    });
                } else {
                    invoicedApplyPaList.forEach(invoicedApplyPaService::removeById);
                }

                invoicedApplyPaList.forEach(invoicedApplyPa -> {
                    //更新预付款已冲账金额
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(invoicedApplyPa.getPaId());
                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                        paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()).compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()));
                        paymentAdvanceApplyDetailService.updateById(paymentAdvanceApplyDetail);
                    }
//                    invoicedApplyPaService.removeById(invoicedApplyPa.getId());
                });

            }
        }
    }

    /**
     * 开票申请提交采购确认
     *
     * @param ids 开票申请ID
     */
    @Override
    @Transactional
    public void submitConfirm(String ids) {
        if (StringUtils.isEmpty(ids)) {
            throw new DaoException("参数异常, 请重新操作");
        }
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        InvoicedApplyQuery query = new InvoicedApplyQuery();
        query.setIaIdList(idList);
        final List<InvoicedApplyPO> oldIaList = invoicedApplyService.selectDataByQuery(null, query);
        for (InvoicedApplyPO ia : oldIaList) {
            if (1 != ia.getStatus() && 3 != ia.getStatus() && 8 != ia.getStatus()) {
                throw new DaoException("开票申请单号: " + ia.getInvoiceApplyNo() + ", 当前数据状态不支持提交确认, 请检查");

            }
        }
        List<InvoicedApply> iaList = Lists.newArrayList();
        for (Long id : idList) {
            InvoicedApply ia = new InvoicedApply();
            ia.setStatus(2);
            ia.setId(id);
            ia.setUpdateTime(LocalDateTime.now());
            ia.setUpdateUserId(LoginUtil.getUserId());
            ia.setUpdateUserCode(LoginUtil.getAccount());
            ia.setUpdateUserName(LoginUtil.getName());
            iaList.add(ia);

            // 增加控制：必须存在关联发票数据，没有则禁止通过
//            List<InvoiceLeShuiDto> invoice = invoicedLesHuiService.getInvoiceDetail(id);
//            if(bindInvoice && CollectionUtils.isEmpty(invoice)){
//                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(this.returnMessage("当前开票申请没有关联发票数据，无法提交！"));
//            }
        }

        if (CollectionUtils.isNotEmpty(iaList)) {
            if (!invoicedApplyService.updateBatchById(iaList)) {
                throw new DaoException("提交确认失败, 请联系管理员");
            }
        }
    }

    /**
     * 采购或财务确认开票申请
     *
     * @param params 开票申请数据
     */
    @Override
    @Transactional
    public void purchaseConfirm(InvoicedApplySaveParamDTO params) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("参数异常, 请重新操作");
        }

//        if (CollectionUtils.isEmpty(params.getDetailDate())) {
//            throw new DaoException("明细数据异常, 请重新操作");
//        }
        InvoicedApplyDTO headDto = params.getHeadData();
        InvoicedApply head = invoicedApplyConvert.dto2Entity(headDto);
        // 变更的开票明细数据
//        List<InvoicedApplyItemDTO> detailList = params.getDetailDate();
        //roleType 1 采购确认 2 财务确认   ApproveStatus 1 同意 0 拒绝
        if (1 == params.getRoleType() && 1 == params.getApproveStatus()) {
//            if(head.getInvoiceTotalAmount().compareTo(head.getInvoiceNetAmount())!=0){
//                throw new RuntimeException("金额不符，请重新关联发票，修改开票金额!");
//            }
//            if(head.getInvoiceTaxTotalAmount().compareTo(head.getInvoiceTaxAmount())!=0){
//                throw new RuntimeException("金额不符，请重新关联发票，修改开票金额!");
//            }

            //判断发票上传的供应商是否一致
//            List<InvoiceLeShuiDto> invoiceDetail = invoicedLesHuiService.getInvoiceDetail(head.getId());
//            Optional<InvoiceLeShuiDto> cartOptional = invoiceDetail.stream().filter(item -> !item.getSellerTaxName().equals(head.getSupplierName())).findFirst();
//            if (cartOptional.isPresent()) {
//                throw new RuntimeException("发票明细关联了其他供应商的发票,请检查!");
//            }

            //开票申请单校验预付款是否被使用
            if (CollectionUtils.isNotEmpty(params.getAddAdvances())) {
                invoicedApplyPaLogic.checkAdvanceUse(params.getAddAdvances(), head.getId());
                //2025-09-06增加采购审核通过保存时，当实际未付金额大于0，判定对账明细中所有订单行是否有未抵扣的预付款金额逻辑校验
//                if(head.getActualUnpaidAmount().compareTo(BigDecimal.ZERO) > 0){
//                    paymentAdvanceApplyDetailLogic.hasUnappliedPrepaymentBalance(head,params.getAddAdvances());
//                }
            }
            //2025-07-31 增加预付款变更单管理订单 已冲账金额反写逻辑
            //2025-08-02 开票申请中预付款明细保存和删除场景
            //1. 正常保存，还没有和主键进行关联的
            //2. 正常删除一行已保存过有主键id的数据，剩下没有保存过的
            //3. 删除一行已保存过的，再新增一行没有保存过的，还有两行已保存过的
            //4. 全部删除,分前台传过来就没有预付款明细，后台通过查询已报存的明细也返回无

            //先按照正常逻辑来
            /**
             * 全部新增反写金额
             */
            List<InvoicedApplyPa> addAdvances = params.getAddAdvances();//前台传过来的预付款明细列表
            //根据开票id查找是否已存在绑定的表里的预付款信息
            List<InvoicedApplyPa> existInvoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, head.getId()));
            if (CollectionUtils.isNotEmpty(existInvoicedApplyPaList) && CollectionUtils.isNotEmpty(addAdvances)) {
                //1.对比出，没有在库里新增过的，进行累加，库里新增过的则跳过不管（因为已经增加过了），库里有页面传过来没有的则是被删除的，需要再减回去
                List<String> existPaList = existInvoicedApplyPaList.stream()//表里已存在的变更单号
                        .filter(item -> item.getPaymentChangeNumber() != null && !item.getPaymentChangeNumber().isEmpty())
                        .filter(item -> item.getPaymentChangeItemNo() != null && !item.getPaymentChangeItemNo().isEmpty())
                        .map(item -> item.getPaymentChangeNumber() + "_" + item.getPaymentChangeItemNo())
                        .collect(Collectors.toList());

                List<String> paramList = addAdvances.stream()  //前台预付款传值列表
                        .filter(item -> item.getPaymentChangeNumber() != null && !item.getPaymentChangeNumber().isEmpty())
                        .filter(item -> item.getPaymentChangeItemNo() != null && !item.getPaymentChangeItemNo().isEmpty())
                        .map(item -> item.getPaymentChangeNumber() + "_" + item.getPaymentChangeItemNo())
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(existPaList) && CollectionUtils.isNotEmpty(paramList)) {
                    //比较出 e有 p没有的 减回去  比较出e没有 p有的 加上去
                    Set<String> existSet = new HashSet<>(existPaList);//表里已存在的
                    Set<String> paramSet = new HashSet<>(paramList);//页面最新传值

                    List<String> onlyInList = existSet.stream()//表里有，页面已经没有了，被删除，需要将金额减回去
                            .filter(e -> !paramSet.contains(e))
                            .collect(Collectors.toList());

                    for (String string : onlyInList) {
                        for (InvoicedApplyPa pa : existInvoicedApplyPaList) {
                            if (string.equals(pa.getPaymentChangeNumber() + "_" + pa.getPaymentChangeItemNo())) {
                                //表里有，页面已经没有了，被删除，需要将金额减回去
                                paymentAdvanceApplyDetailLogic.updateReversedAmount(pa.getPaymentChangeNumber(), pa.getPaymentChangeItemNo(), pa.getStrikePrice().negate());
                            }
                        }
                    }
                    // paramList有而existPaList没有 需要增加
                    List<String> onlyInList1 = paramSet.stream()
                            .filter(e -> !existSet.contains(e))
                            .collect(Collectors.toList());
                    for (String string : onlyInList1) {
                        for (InvoicedApplyPa paramApplyPa : addAdvances) {
                            if (string.equals(paramApplyPa.getPaymentChangeNumber() + "_" + paramApplyPa.getPaymentChangeItemNo())) {
                                //表里没有，页面有，属于新增，需要将金额加上去
                                paymentAdvanceApplyDetailLogic.updateReversedAmount(paramApplyPa.getPaymentChangeNumber(), paramApplyPa.getPaymentChangeItemNo(), paramApplyPa.getStrikePrice());
                            }
                        }
                    }
                }
                if (CollectionUtils.isEmpty(existPaList) && CollectionUtils.isNotEmpty(paramList)) { //表里没变更单号，页面传值有变更单号
                    //全部加上去
                    for (InvoicedApplyPa addAdvance : addAdvances) {//页面新绑定的带预付款变更单号的数据
                        String paymentChangeNumber = addAdvance.getPaymentChangeNumber();
                        String paymentChangeItemNo = addAdvance.getPaymentChangeItemNo();
                        if (StringUtils.isNotEmpty(paymentChangeNumber) && StringUtils.isNotEmpty(paymentChangeItemNo)) {
                            //只存在有变更单的预付款明细需要更新已冲账金额
                            paymentAdvanceApplyDetailLogic.updateReversedAmount(paymentChangeNumber, paymentChangeItemNo, addAdvance.getStrikePrice());
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(existPaList) && CollectionUtils.isEmpty(paramList)) {
                    //全部减回去
                    for (InvoicedApplyPa invoicedApplyPa : existInvoicedApplyPaList) {
                        String paymentChangeNumber = invoicedApplyPa.getPaymentChangeNumber();
                        String paymentChangeItemNo = invoicedApplyPa.getPaymentChangeItemNo();
                        if (StringUtils.isNotEmpty(paymentChangeNumber) && StringUtils.isNotEmpty(paymentChangeItemNo)) {
                            //页面没有带变更单号的，表里有变更单号，说明已被修改删除更新已冲账金额
                            paymentAdvanceApplyDetailLogic.updateReversedAmount(paymentChangeNumber, paymentChangeItemNo, invoicedApplyPa.getStrikePrice().negate());
                        }
                    }
                }


            } else if (CollectionUtils.isNotEmpty(addAdvances) && CollectionUtils.isEmpty(existInvoicedApplyPaList)) {
                for (InvoicedApplyPa addAdvance : params.getAddAdvances()) {//页面新绑定的带预付款变更单号的数据
                    String paymentChangeNumber = addAdvance.getPaymentChangeNumber();
                    String paymentChangeItemNo = addAdvance.getPaymentChangeItemNo();
                    if (StringUtils.isNotEmpty(paymentChangeNumber) && StringUtils.isNotEmpty(paymentChangeItemNo)) {
                        //更新已冲账金额
                        paymentAdvanceApplyDetailLogic.updateReversedAmount(paymentChangeNumber, paymentChangeItemNo, addAdvance.getStrikePrice());
                    }
                }
            } else if (CollectionUtils.isEmpty(params.getAddAdvances()) && CollectionUtils.isNotEmpty(existInvoicedApplyPaList)) {
                //找出存在的预付款变更单号把金额减掉
                for (InvoicedApplyPa invoicedApplyPa : existInvoicedApplyPaList) {
                    String paymentChangeNumber = invoicedApplyPa.getPaymentChangeNumber();
                    String paymentChangeItemNo = invoicedApplyPa.getPaymentChangeItemNo();
                    if (StringUtils.isNotEmpty(paymentChangeNumber) && StringUtils.isNotEmpty(paymentChangeItemNo)) {
                        //页面预付款明细为空，数据库有关联预付款变更单需要更新已冲账金额
                        paymentAdvanceApplyDetailLogic.updateReversedAmount(paymentChangeNumber, paymentChangeItemNo, invoicedApplyPa.getStrikePrice().negate());
                    }
                }
            }
        }

        // 本次变更可能存在新增的明细数据
//        List<InvoicedApplyDetail> newDetailList = Lists.newArrayList();
//        List<InvoicedApplyDetail> currDetailList = Lists.newArrayList();
//        for (InvoicedApplyItemDTO detail : detailList) {
//            if (0 == detail.getId()) {
//                newDetailList.add(detail.toIad());
//            } else {
//                currDetailList.add(detail.toIad());
//            }
//        }

        // 变更前的开票申请明细数据
        final List<InvoicedApplyDetail> oldIadList = invoicedApplyDetailService.findByInvoiceApplyId(head.getId(), Lists.newArrayList());
        // 变更前开票申请表头数据
        final InvoicedApply oldHead = invoicedApplyService.getById(head.getId());
//        if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//            oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//        }
        //采购审批
        if (1 == params.getRoleType()) {
            // 数据状态 2:待采购确认 3:采购拒绝 6:OA审批不通过 8:财务拒绝
            if (2 != oldHead.getStatus() && 3 != oldHead.getStatus() && 6 != oldHead.getStatus() && 8 != oldHead.getStatus()) {
                throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
            }
            // 将有可能变更的数据放到原开票申请对象中
//            oldHead.setInvoiceNo(head.getInvoiceNo());
//            oldHead.setInvoiceNum(head.getInvoiceNum());
            oldHead.setInvoiceNetAmount(head.getInvoiceNetAmount());
            oldHead.setInvoiceTaxAmount(head.getInvoiceTaxAmount());
//            oldHead.setRebateAmount(head.getRebateAmount());
//            oldHead.setRntAmount(head.getRntAmount());
//            oldHead.setDeductionAmount(head.getDeductionAmount());
//            oldHead.setDntAmount(head.getDntAmount());
//            oldHead.setInvoiceTotalAmount(head.getInvoiceTotalAmount());
//            oldHead.setAllBudInnerMoney(head.getAllBudInnerMoney());
//            oldHead.setInvoiceTaxTotalAmount(head.getInvoiceTaxTotalAmount());
            oldHead.setRemark(head.getRemark());
//            oldHead.setTaxCode(head.getTaxCode());
            oldHead.setStrikePriceAmount(head.getStrikePriceAmount());
            oldHead.setActualUnpaidAmount(head.getActualUnpaidAmount());
//            if (null!=head.getStrikePriceAmount()){
//                if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//                    oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//                }
//            }
//            oldHead.setDeductionAmountTotal(head.getDeductionAmountTotal());
            oldHead.setStrikeStatus(CollectionUtils.isNotEmpty(params.getAddAdvances()) ? 0 : 3);

            oldHead.setLocalCurrency(head.getLocalCurrency());
            oldHead.setOriginalCurrency(head.getOriginalCurrency());
            oldHead.setAdvanceLocalCurrency(head.getAdvanceLocalCurrency());
            oldHead.setAdvanceOriginalCurrency(head.getAdvanceOriginalCurrency());

            if (1 == params.getApproveStatus()) {
                // 设置确认日志
                if (CollectionUtils.isNotEmpty(params.getLogDetailList())) {
                    setConfirmLog(params.getLogDetailList(), oldHead.getId(), oldHead.getAccountStatementNo());
                }
            }
            this.purchaseConfirm(
                    oldHead, null, params.getDelDetailIds(), params.getDelSdIds(), params.getDelSrIds(),
                    params.getAddSdIds(), params.getAddSrIds(), params.getApproveRemark(), params.getApproveStatus(), LoginUtil.getCurrentUser(),params.getManualCheckList()
            );
            if (CollectionUtils.isNotEmpty(params.getAddAdvances()) && 0 == params.getApproveStatus()) {
                List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, head.getId()));
                invoicedApplyPaList.forEach(invoicedApplyPa -> {
                    //2025-09-03 如果预付款里关联了变更单，则不更新预付款里的已冲账金额
                    if (StringUtils.isEmpty(invoicedApplyPa.getPaymentChangeNumber()) && StringUtils.isEmpty(invoicedApplyPa.getPaymentChangeItemNo())) {
                        //更新预付款已冲账金额
                        PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(invoicedApplyPa.getPaId());
                        if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                            paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()).compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()));
                            paymentAdvanceApplyDetailService.updateById(paymentAdvanceApplyDetail);
                        }
                    }
                });
            }
            invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, head.getId()));
            if (CollectionUtils.isNotEmpty(params.getAddAdvances()) && 1 == params.getApproveStatus()) {
                List<InvoicedApplyPa> paList = Lists.newArrayList();
                List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
                for (InvoicedApplyPa ipa : params.getAddAdvances()) {
                    ipa.setInvoiceApplyId(head.getId());
                    ipa.setId(null);
                    ipa.setDeleteFlag(0);
//                    ipa.setPaId(paId);
                    paList.add(ipa);
//
//                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = new PaymentAdvanceApplyDetail();
//                    paymentAdvanceApplyDetail.setId(paId);
//                    //发票申请消费标识 0：未消费 1；已消费
//                    paymentAdvanceApplyDetail.setInvoicedFlag(1);
//                    paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                    //2025-09-03增加如果预付款里关联了变更单，则不更新预付款里的已冲账金额
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());
                    if (StringUtils.isEmpty(ipa.getPaymentChangeNumber()) && StringUtils.isEmpty(ipa.getPaymentChangeItemNo())) {
                        //更新预付款已冲账金额
                        if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                            paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().add(ipa.getStrikePrice()));
                        }
                    }
                    paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                }

                if (!this.invoicedApplyPaService.saveBatch(paList)) {
                    throw new DaoException("保存预付款申请明细失败, 前联系管理员");
                }
                if (!this.paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList)) {
                    throw new DaoException("更新预付款申请明细失败, 前联系管理员");
                }

            }

            invoicedApplyOptLogic.addContentRecord(1, null, null, Lists.newArrayList(), null, LoginUtil.getCurrentUser());
            invoicedApplyOptLogic.addContentRecord(2, oldHead, head, oldIadList, null, LoginUtil.getCurrentUser());

        } else {//财务审批 roleType = 2  通过1 拒绝是0
            // 数据状态 7:待财务确认
            if (7 != oldHead.getStatus()) {
                throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
            }
//            oldHead.setStrikePriceAmount(head.getStrikePriceAmount());
//            oldHead.setActualUnpaidAmount(head.getActualUnpaidAmount());
//            if (null!=head.getStrikePriceAmount()){
//                if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//                    oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//                }
//            }
//            oldHead.setDeductionAmountTotal(head.getDeductionAmountTotal());
            oldHead.setRemark(head.getRemark());
            this.financeConfirm(oldHead, params.getApproveRemark(), params.getApproveStatus(), LoginUtil.getCurrentUser(), params.getManualCheckList());
        }

        // 保存关联发票信息
        invoicedReceiptLogic.operateInvoice(params.getInvoicedReceiptData(), head.getId(), LoginUtil.getCurrentUser());
    }

    @Override
    public List<String> confirmCheck(InvoicedApplySaveParamDTO params) {
        List<String> resultList = new ArrayList<>();
        InvoicedApply accountStatement = invoicedApplyService.getById(params.getHeadData().getId());
        //统计“在途退款金额”
        BigDecimal refundAmount = receiptVoucherLogic.getReturnVoucherRefundAmount(accountStatement.getSupplierCode(),accountStatement.getFactoryCode(),accountStatement.getCompanyCode(),true);
        if (refundAmount.compareTo(BigDecimal.valueOf(0.5))>0||refundAmount.compareTo(BigDecimal.valueOf(-0.5))<0){
            resultList.add(StrUtil.format("该供应商存在在途退款金额【{}】，请及时处理", refundAmount.stripTrailingZeros().toPlainString()));
        }

        Deduction deduction = deductionService.getOne(new LambdaQueryWrapper<>(Deduction.class)
                .eq(Deduction::getSupplierCode, accountStatement.getSupplierCode())
                .eq(Deduction::getDeleteFlag, 0)
                .ne(Deduction::getStatus, 3).last(" limit 1")
        );
        if (ObjectUtil.isNotNull(deduction)){
            resultList.add(StrUtil.format("该供应商存在未完成的质量扣款单【{}】，请及时处理", deduction.getDeductionNo()));
        }

        return resultList;
    }

    /**
     * 设置确认日志
     * @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);
    }

    @Override
    @Transactional
    public void saleContractConfirm(InvoicedApplySaveParamDTO params) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("参数异常, 请重新操作");
        }
        InvoicedApplyDTO headDto = params.getHeadData();
        invoicedApplyService.update(new LambdaUpdateWrapper<InvoicedApply>()
                .set(InvoicedApply::getContractSupplementStatus, params.getApproveStatus() == 1 ? 3 : 2)
                .set(InvoicedApply::getContractSupplementRemark, params.getApproveRemark())
                .eq(InvoicedApply::getId, headDto.getId()));

        this.toImg(headDto.getId());
        this.toAllImg(headDto.getId());
    }

    /**
     * 采购撤销待财务确认状态的开票申请
     *
     * @param iaId         开票申请ID
     * @param revokeReason 撤销原因
     */
    @Override
    public void revokeFinConfirm(Long iaId, String revokeReason) {
        if (null == iaId) {
            throw new DaoException("参数错误");
        }
        final InvoicedApply apply = invoicedApplyService.getById(iaId);
        if (null == apply) {
            throw new DaoException("系统未找到相应的开票申请信息");
        }
        if (7 != apply.getStatus()) {
            throw new DaoException("开票申请不能进行撤销操作, 请检查开票申请状态");
        }

        InvoicedApply updateHead = new InvoicedApply();
        updateHead.setId(apply.getId());
        updateHead.setStatus(2);
        updateHead.setUpdateUserId(LoginUtil.getUserId());
        updateHead.setUpdateUserCode(LoginUtil.getAccount());
        updateHead.setUpdateUserName(LoginUtil.getName());
        updateHead.setUpdateTime(LocalDateTime.now());
        invoicedApplyService.updateById(updateHead);

        //查询已经关联预付款数据，如果有就减去上次冲账金额且删除
        List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, apply.getId()));
        if (CollectionUtils.isNotEmpty(invoicedApplyPaList)) {
            List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
            invoicedApplyPaList.forEach(ipa -> {
                PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());

                //查询预付款转单变更信息
                if (StringUtils.isNotEmpty(ipa.getPaymentChangeNumber()) && StringUtils.isNotEmpty(ipa.getPaymentChangeItemNo())) {
                    //撤回时，更新金额会去（减去相应的申请金额）
                    paymentAdvanceApplyDetailLogic.updateReversedAmount(ipa.getPaymentChangeNumber(), ipa.getPaymentChangeItemNo(), ipa.getStrikePrice().negate());
                } else {
                    paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()).compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()));
                }
                if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                    paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                }
            });
            paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList);
            invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, apply.getId()));


        }

        // 2.记录撤销原因
        InvoicedApplyApprove approve = new InvoicedApplyApprove();
        approve.setIaId(apply.getId());
        approve.setIaNo(apply.getInvoiceApplyNo());
        approve.setApproveResult(2);
        approve.setApproveOpinion(revokeReason);
        approve.setApproveUserId(LoginUtil.getUserId());
        approve.setApproveUserCode(LoginUtil.getAccount());
        approve.setApproveUserName(LoginUtil.getName());
        // 撤销只能由采购操作
        approve.setApproveNode(1);
        approve.setApproveTime(LocalDateTime.now());
        invoicedApplyApproveService.save(approve);
    }

    @Override
    public void updateNewDate(Long iaId, String newPaymentExpireDate) {
        if (null == iaId) {
            throw new DaoException("参数错误");
        }
        final InvoicedApply apply = invoicedApplyService.getById(iaId);
        if (null == apply) {
            throw new DaoException("系统未找到相应的开票申请信息");
        }
        if (9 != apply.getStatus()) {
//            throw new DaoException("开票申请不能进行修改操作, 请检查开票申请状态");
        }

        InvoicedApply updateHead = new InvoicedApply();
        updateHead.setId(apply.getId());
        updateHead.setUpdateUserId(LoginUtil.getUserId());
        updateHead.setUpdateUserCode(LoginUtil.getAccount());
        updateHead.setUpdateUserName(LoginUtil.getName());
        updateHead.setUpdateTime(LocalDateTime.now());
        newPaymentExpireDate = newPaymentExpireDate.replace(" ", "").replace("00:00:00", "");
        updateHead.setNewPaymentExpireDate(DateUtils.formatYYYYMMDDDash(newPaymentExpireDate));
        invoicedApplyService.updateById(updateHead);
    }

    /**
     * 财务取消确认
     *
     * @param ids 开票申请IDs
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void financeConfirmCancel(String ids) {
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        for (Long invoiceApplyId : idList) {
            InvoicedApply old = invoicedApplyService.getById(invoiceApplyId);
            InvoicedApply updateHead = new InvoicedApply();
            updateHead.setId(invoiceApplyId);
            updateHead.setUpdateTime(LocalDateTime.now());
            updateHead.setUpdateUserId(LoginUtil.getUserId());
            updateHead.setUpdateUserCode(LoginUtil.getAccount());
            updateHead.setUpdateUserName(LoginUtil.getName());
            // 数据状态 1:暂存发票 2:待采购确认发票 3:采购拒绝发票 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认发票 8:财务驳回发票 9:发票已确认
            updateHead.setStatus(7);
            updateHead.setPostStatus(1);
            if (!invoicedApplyService.updateById(updateHead)) {
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }
            if (!invoicedApplyPostResultService.remove(Wrappers.lambdaQuery(InvoicedApplyPostResult.class).eq(InvoicedApplyPostResult::getInvoiceApplyId, invoiceApplyId))) {
                throw new DaoException("删除开票申请单待过账记录失败, 请联系管理员");
            }
            PayableRefund payableRefund = payableRefundService.getOne(Wrappers.lambdaQuery(PayableRefund.class)
                    .eq(PayableRefund::getDzdh, old.getAccountStatementNo())
                    .eq(PayableRefund::getQxsk, 0)
                    .last(" LIMIT 1"));
            if (ObjectUtil.isNotNull(payableRefund)){
                throw new DaoException("对账单"+old.getAccountStatementNo()+"已退款，不允许取消确认");
            }
            //取消发票确认
            List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(new LambdaQueryWrapper<>(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, invoiceApplyId));
            if (CollUtil.isNotEmpty(invoicedReceipts)) {
                //提取serialNo不为空的数据为list<String>
                List<String> serialNoList = invoicedReceipts.stream()
                        .map(InvoicedReceipt::getSerialNo)
                        .filter(StrUtil::isNotEmpty)
                        .toList();
                if (CollUtil.isNotEmpty(serialNoList)) {
                    kingdeeInvoiceCloudLogic.billSign(String.valueOf(invoiceApplyId), "02", String.join(",", serialNoList));
                }
            }
            // 2.记录撤销原因
            InvoicedApplyApprove approve = new InvoicedApplyApprove();
            approve.setIaId(old.getId());
            approve.setIaNo(old.getInvoiceApplyNo());
            approve.setApproveResult(3);
            approve.setApproveOpinion("财务取消确认");
            approve.setApproveUserId(LoginUtil.getUserId());
            approve.setApproveUserCode(LoginUtil.getAccount());
            approve.setApproveUserName(LoginUtil.getName());
            // 撤销只能由采购操作
            approve.setApproveNode(2);
            approve.setApproveTime(LocalDateTime.now());
            invoicedApplyApproveService.save(approve);

            PayableDeleteDTO payImportToOpenDTO = new PayableDeleteDTO();
            payImportToOpenDTO.setBillno(old.getAccountStatementNo());
            if (StrUtil.isEmpty(old.getFinancePayablePostId())){
                continue;
            }
            //提交到共享
            String accessToken = financialShareUtil.getShareAccessToken();
            ErpApiResult1<PayImportToOpenResultDTO> result = paymentOaClient.payableDelete(accessToken,payImportToOpenDTO);
            if (!result.getStatus()) {
                throw new DaoException("共享系统接口报错：" + result.getMessage());
            }
            updateHead.setFinancePayablePostStatus(0);
            if (!invoicedApplyService.updateById(updateHead)) {
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }
        }
    }

    @Override
    @DS(SLAVE)
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW,noRollbackFor = DaoException.class )
    public void updatePurchaseOrderFin(String ids) {
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        Set<String> orderList = new HashSet<>();
        for (Long invoiceApplyId : idList) {
            InvoicedApply invoicedApply = invoicedApplyService.getById(invoiceApplyId);
            List<StatementItemDTO> asdList = accountStatementDetailLogic.findByStatementId(invoicedApply.getAccountStatementId(),invoicedApply.getFactoryCode());
            for (StatementItemDTO statementItemDTO : asdList) {
                orderList.add(statementItemDTO.getPoCode());
            }
        }
        if (CollUtil.isNotEmpty(orderList)){

            purchaseOrderClient.updateFinConf(orderList,LoginUtil.getUserId());
        }

    }
    /**
     * 财务取消确认
     *
     * @param ids 开票申请IDs
     */
    @Override
    @DS(SLAVE)
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW,noRollbackFor = DaoException.class )
    public void payableSend(String ids) {
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        for (Long invoiceApplyId : idList) {
            InvoicedApply invoicedApply = invoicedApplyService.getById(invoiceApplyId);
            if (invoicedApply.getFinancePayablePostStatus()==1){
                throw new DaoException("已推送财务应付单，请勿重复提交");
            }

            //提交到共享
            String accessToken = financialShareUtil.getShareAccessToken();
            PayableToOpenDTO payImportToOpenDTO = new PayableToOpenDTO();
            PayableToOpenDTO.DataHead dataHead = new PayableToOpenDTO.DataHead();
            // 单据编号
            dataHead.setOrg_number(invoicedApply.getCompanyCode());
            dataHead.setPayorg_number(invoicedApply.getCompanyCode());
            dataHead.setBillno(invoicedApply.getAccountStatementNo());
            dataHead.setBizdate(LocalDateTimeUtil.format(invoicedApply.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            dataHead.setAsstact_number(invoicedApply.getSupplierCode());
            dataHead.setReceivingsupplierid_number(invoicedApply.getSupplierCode());
            if ( invoicedApply.getPaymentWay().equals("B")) {
                // 付款方式.编码
                dataHead.setSettlementtype_number("101");
            } else if (invoicedApply.getPaymentWay().equals("C")) {
                // 付款方式.编码
                dataHead.setSettlementtype_number("201");
            } else if (invoicedApply.getPaymentWay().equals("D")) {
                // 付款方式.编码
                dataHead.setSettlementtype_number("701");
            }
//            dataHead.setcurrency_number("admin".equals(LoginUtil.getAccount()) ? "ID-000005" : LoginUtil.getAccount());
            dataHead.setCurrency_number(invoicedApply.getCurrencyCode());
            dataHead.setSourcebilltype("3");

            List<PayableToOpenDTO.Entry> entryList = new ArrayList<>();
            List<StatementItemDTO> asdList = accountStatementDetailLogic.findByStatementId(invoicedApply.getAccountStatementId(),invoicedApply.getFactoryCode());
            for (StatementItemDTO asd : asdList) {
                PayableToOpenDTO.Entry entry = new PayableToOpenDTO.Entry();
                String id = String.valueOf(asd.getId());
                //id不足20位，需要补0，保证id长度20位
                id = StrUtil.padAfter(id, 15, "0");
                entry.setId(Long.valueOf(id));
                // 物料编码
//                entry.setMaterial_number(asd.getMaterialCode());
                // 计量单位.编码
//                String materialUnit = asd.getMaterialUnit();
                //materialUnit字母转小写
//                materialUnit = materialUnit.toLowerCase();
//                entry.setMeasureunit_number(materialUnit);
                // 数量
                entry.setQuantity(asd.getReceiveNum().stripTrailingZeros().toPlainString());
                // 单价
                entry.setPrice(asd.getOrderNotTaxPrice()==null?"0":asd.getOrderNotTaxPrice().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                entry.setPricetax(asd.getOrderTaxPrice()==null?"0":asd.getOrderTaxPrice().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                entry.setE_amount(asd.getNotTaxAmount()==null?"0":asd.getNotTaxAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                entry.setE_pricetaxtotal(asd.getTaxAmount()==null?"0":asd.getTaxAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                // 明细.税率
                TaxDTO taxDTO = taxClient.getByCode(asd.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.setTaxrateid_number(taxCode);
                }
                entry.setM4p4_statement_number(invoicedApply.getAccountStatementNo());
                entryList.add(entry);
            }

            dataHead.setDetailentry(entryList);


            List<PayableToOpenDTO.Entry1> entryList1 = new ArrayList<>();
            List<InvoicedReceipt> invoicedReceiptList = invoicedReceiptService.list(new LambdaQueryWrapper<>(InvoicedReceipt.class)
                    .eq(InvoicedReceipt::getIaId, invoiceApplyId));
            if (CollUtil.isNotEmpty(invoicedReceiptList)){
                for (InvoicedReceipt invoicedReceipt : invoicedReceiptList) {
                    PayableToOpenDTO.Entry1 entry1 = new PayableToOpenDTO.Entry1();
                    //invoicedReceipt.getId()不足十位，需要补0，保证id长度十位
                    String id = String.valueOf(invoicedReceipt.getId());
                    id = StrUtil.padAfter(id, 11, "0");
                    entry1.setId(id);
                    entry1.setM4p4_invoice_type(String.valueOf(invoicedReceipt.getType()));
                    //TODO
                    entry1.setM4p4_deductible_number(invoicedReceipt.getDeductionCodeType()==2?"不可抵扣":"可抵扣");
                    entry1.setM4p4_i_invoicecode(invoicedReceipt.getInvoiceCode());
                    entry1.setM4p4_i_invoiceno(StrUtil.isEmpty(invoicedReceipt.getInvoiceNumber())?invoicedReceipt.getElectronInvoiceNumber():invoicedReceipt.getInvoiceNumber());
                    TaxDTO taxDTO = taxClient.getByCode(invoicedReceipt.getTaxRate());
                    entry1.setM4p4_i_taxrate(taxDTO.getTaxValue().multiply(BigDecimal.valueOf(100)).stripTrailingZeros().toPlainString());
                    entry1.setM4p4_i_invoicedate(DateUtil.format(invoicedReceipt.getInvoiceDate(), "yyyy-MM-dd"));
                    entry1.setM4p4_invoice_company(invoicedApply.getSupplierName());
                    CompanyDTO companyDTO = companyClient.getByCode(invoicedApply.getCompanyCode());
                    entry1.setM4p4_collection_agency(companyDTO.getCompanyName());
                    entry1.setM4p4_i_currency_number(invoicedApply.getCurrencyCode());
                    entry1.setM4p4_tax_amount(invoicedReceipt.getTaxAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    entry1.setM4p4_tax_amount_no(invoicedReceipt.getNoTaxAmount().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
                    entry1.setM4p4_i_tax(invoicedReceipt.getDiffTaxMoney().setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());

                    entryList1.add(entry1);
                }
            }
            dataHead.setM4p4_inventry(entryList1);

            payImportToOpenDTO.setData(dataHead);
            ErpApiResult<PayImportToOpenResultDTO> result = paymentOaClient.payableToOpen(accessToken, payImportToOpenDTO);
            if (!result.getStatus()) {
                invoicedApply.setFinancePayablePostStatus(2);
                invoicedApply.setFinancePayablePostMsg(result.getMessage());
                invoicedApplyService.updateById(invoicedApply);
                throw new DaoException("共享系统接口报错：" + result.getMessage());
            }
            String shareId = result.getData().getResult().get(0).getId();
            invoicedApply.setFinancePayablePostId(shareId);
            invoicedApply.setFinancePayablePostStatus(1);
            invoicedApplyService.updateById(invoicedApply);
        }
    }

    /**
     * 数据导出
     *
     * @param request  请求体
     * @param response 返回体
     * @param id       开票申请单ID
     */
    @Override
    public void dataExport(HttpServletRequest request, HttpServletResponse response, Long id) {
        try {
            final InvoicedApply head = invoicedApplyService.getById(id);
            final List<InvoicedApplyItemPO> iaiList = invoicedApplyDetailService.providePurchaseConfirm(id);
//            final List<InvoicedApplyRebateDto> irList = invoicedApplySrService.findByInvoicedApplyId(id);
//            final List<InvoicedApplyDeductionDto> idList = invoicedApplySdService.findByInvoicedApplyId(id);
            final String fileName = "开票申请单_" + head.getInvoiceApplyNo() + "_导出" + DateTime.now().toString("yyyyMMddHHmmss");
            final XSSFWorkbook workbook = this.handleExportData(head, iaiList);
            response.reset();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            String exportTitle = fileName + ".xlsx";
            OutputStream os = null;
            try {
                String agent = request.getHeader(HttpHeaders.USER_AGENT);
                String enableFileName = EasyExcelUtils.parseAgentDownloadFIleName(exportTitle, agent);
                response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName=" + enableFileName);
                os = response.getOutputStream();
                workbook.write(os);
                os.flush();
            } catch (UnsupportedEncodingException e) {
                LOGGER.error("file name encoding has error!" + e);
            } finally {
                IOUtils.closeQuietly(os);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new DaoException("导出出现错误");
        }
    }

    @Override
    public InvoicedApplyPrintDTO selectPrintDataById(Long id) {
        InvoicedApplyPrintPO dto = invoicedApplyService.selectPrintDataById(id);
        //获取汇率
//        if (!"CNY".equals(dto.getCurrencyCode())){
//            SapExchangeRate sapExchangeRate = sapExchangeRateService.selectOne(Condition.create().eq("original_currency",dto.getCurrencyCode()).eq("month_date",DateUtil.format(new Date(),"yyyyMM")+"01").last(" limit 1"));
//            dto.setExchangeRate(ObjectUtil.isNull(sapExchangeRate)?BigDecimal.ONE:sapExchangeRate.getExchange());
//            dto.setExchangeRateName(ObjectUtil.isNull(sapExchangeRate)?"没有获取到":sapExchangeRate.getExchange()+"("+sapExchangeRate.getMonthDate()+")");
//        }else {
//            dto.setExchangeRate(BigDecimal.ONE);
//            dto.setExchangeRateName("1");
//        }
        dto.setDeductionCodeTypeName(dto.getDeductionCodeType() != null && dto.getDeductionCodeType() == 1 ? "可抵扣" : "不可抵扣");
        return invoicedApplyConvert.invoicedApplyPrintPO2DTO(dto);
    }

    /**
     * 查询预制发票号
     *
     * @param id
     * @return
     */
    @Override
    public String findInvoiceVoucher(Long id) {
        return invoicedApplyService.findInvoiceVoucher(id);
    }

    /**
     * 查询货到付款信息
     *
     * @param query
     * @return
     */
    @Override
    public List<CreatePcaDetailPO> readCodPaymentInvoiceData(PaymentApplyItemQuery query) {
        return invoicedApplyService.readCodPaymentInvoiceData(query);
    }

    @Override
    public void writeOff(Long id, String writeOff) {
        invoicedApplyService.update(new LambdaUpdateWrapper<InvoicedApply>()
                .set(InvoicedApply::getWriteOff, writeOff)
                .eq(InvoicedApply::getId, id)
        );
    }

    /**
     * 处理对账单数据
     *
     * @param head    开票申请单表头数据
     * @param iaiList 开票申请单明细数据
     * @return 结果
     */
    private XSSFWorkbook handleExportData(
            InvoicedApply head, List<InvoicedApplyItemPO> iaiList
    ) {
        // Excel工作表格对象处理
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet();
        sheet.setPrintGridlines(false);
        workbook.setSheetName(0, head.getInvoiceApplyNo());
        XSSFCellStyle cellStyle = workbook.createCellStyle();

        int dataIndex = 0;

        // 处理主表数据
        dataIndex = this.handleTableHeadData(head, dataIndex, workbook, sheet, cellStyle);

        // 两个表格之间的间隙
        dataIndex += 1;

        // 表头样式
        CellStyle headerStyle = workbook.createCellStyle();
        // 水平居中
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 表头字体
        Font headerFont = workbook.createFont();
        headerFont.setFontHeightInPoints((short) 12);
        headerStyle.setFont(headerFont);

        // 表格名称单元格样式
        cellStyle = workbook.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

//        // 开票申请单返利数据
//        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 2));
//        XSSFRow titleRow1 = sheet.createRow(dataIndex);
//        titleRow1.setHeight((short) (25 * 20));
//        XSSFCell titleCell1 = titleRow1.createCell(0);
//        titleCell1.setCellValue("一、返利信息");
//        titleCell1.setCellStyle(cellStyle);

//        dataIndex += 1;
//
//        // 第一个数据表格表头
//        List<String> tableTitle1 = Lists.newArrayList();
//        List<Map<String, String>> tableData1 = this.irDataTransformMap(tableTitle1, irList);
//        // 写入表头
//        XSSFRow row1 = sheet.createRow(dataIndex);
//        for (int i = 0; i < tableTitle1.size(); i++) {
//            XSSFCell row1Cell = row1.createCell(i);
//            row1Cell.setCellValue(tableTitle1.get(i));
//            row1Cell.setCellStyle(headerStyle);
//        }
//        // 写入数据
//        dataIndex += 1;
//        ExportExcelCommonUtil.writeDataRow(sheet, dataIndex, tableTitle1, tableData1);
//
//        // 两个表格之间的间隙(解释一下为啥减1又1, 减1是获取数据行写入后Excel行索引位置, 加1是指下一行开始行索引)
//        dataIndex = dataIndex + tableData1.size() - 1 + 1;
//
//        // 对账单扣款数据
//        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 2));
//        XSSFRow titleRow2 = sheet.createRow(dataIndex);
//        titleRow2.setHeight((short) (25 * 20));
//        XSSFCell titleCell2 = titleRow2.createCell(0);
//        titleCell2.setCellValue("二、扣款信息");
//        titleCell2.setCellStyle(cellStyle);
//        dataIndex += 1;
//
//        // 第二个数据表格表头
//        List<String> tableTitle2 = Lists.newArrayList();
//        // 第二个数据表格数据
//        List<Map<String, String>> tableData2 = this.idDataTransformMap(tableTitle2, idList);
//        // 写入表头
//        XSSFRow row2 = sheet.createRow(dataIndex);
//        for (int i = 0; i < tableTitle2.size(); i++) {
//            XSSFCell row2Cell = row2.createCell(i);
//            row2Cell.setCellValue(tableTitle2.get(i));
//            row2Cell.setCellStyle(headerStyle);
//        }

//        // 写入数据
//        dataIndex += 1;
//        ExportExcelCommonUtil.writeDataRow(sheet, dataIndex, tableTitle2, tableData2);
//
//        // 两个表格之间的间隙(解释一下为啥减1又1, 减1是获取数据行写入后Excel行索引位置, 加1是指下一行开始行索引)
//        dataIndex = dataIndex + tableData2.size() - 1 + 1;

        // 对账单明细数据
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 2));
        XSSFRow titleRow3 = sheet.createRow(dataIndex);
        titleRow3.setHeight((short) (25 * 20));
        XSSFCell titleCell3 = titleRow3.createCell(0);
        titleCell3.setCellValue("明细信息");
        titleCell3.setCellStyle(cellStyle);
        dataIndex += 1;

        // 第二个数据表格表头
        List<String> tableTitle3 = Lists.newArrayList();
        // 第二个数据表格数据
        List<Map<String, String>> tableData3 = this.iaiDataTransformMap(tableTitle3, iaiList);
        // 写入表头
        XSSFRow row3 = sheet.createRow(dataIndex);
        for (int i = 0; i < tableTitle3.size(); i++) {
            XSSFCell row3Cell = row3.createCell(i);
            row3Cell.setCellValue(tableTitle3.get(i));
            row3Cell.setCellStyle(headerStyle);
        }

        // 写入数据
        dataIndex += 1;

        for (Map<String, String> data : tableData3) {
            XSSFRow dataRow = sheet.createRow(dataIndex);
            for (int i = 0; i < tableTitle3.size(); i++) {
                XSSFCell dataCell = dataRow.createCell(i);
                dataCell.setCellValue(data.get(tableTitle3.get(i)));
            }
            dataIndex++;
        }

        return workbook;
    }

    /**
     * 处理开票申请单明细数据便于导出
     *
     * @param tableTitle 开票申请明细表格表头
     * @param iaiList    开票申请单明细数据
     * @return 结果
     */
    private List<Map<String, String>> iaiDataTransformMap(List<String> tableTitle, List<InvoicedApplyItemPO> iaiList) {
        tableTitle.add("对账单号");
        tableTitle.add("对账单行号");
        tableTitle.add("对账数量");
        tableTitle.add("到票未税单价");
        tableTitle.add("到票含税单价");
        tableTitle.add("到票未税金额");
        tableTitle.add("到票含税金额");
        tableTitle.add("到票税率");
        tableTitle.add("到票税额");
        tableTitle.add("对账未税单价");
        tableTitle.add("对账含税单价");
        tableTitle.add("对账未税金额");
        tableTitle.add("对账含税金额");
        tableTitle.add("对账税率");
        tableTitle.add("对账税额");
        tableTitle.add("入库凭证");
        tableTitle.add("入库时间");
        tableTitle.add("物料编码");
        tableTitle.add("物料名称");
        tableTitle.add("单位");
        tableTitle.add("SAP订单号");
        tableTitle.add("订单行号");
//        tableTitle.add("询源采购组");
//        tableTitle.add("订单税率");
//        tableTitle.add("付款方式");
        tableTitle.add("付款条件");
//        tableTitle.add("原材料商");
        List<Map<String, String>> result = Lists.newArrayList();
        for (InvoicedApplyItemPO dto : iaiList) {
            Map<String, String> map = Maps.newHashMap();
            map.put("对账单号", dto.getAsNo());
            map.put("对账单行号", dto.getAsdItemNo());
            map.put("对账数量", dto.getStatementNum().toString());
            map.put("到票未税单价", dto.getNotTaxPrice().toString());
            map.put("到票含税单价", dto.getTaxPrice().toString());
            map.put("到票未税金额", dto.getNotTaxAmount().toString());
            map.put("到票含税金额", dto.getTaxAmount().toString());
            map.put("到票税率", dto.getTaxCode() + "(" + dto.getTaxValue() + "%)");
            map.put("到票税额", dto.getDiffTaxAmount().toString());
            map.put("对账未税单价", dto.getAsNotTaxPrice().toString());
            map.put("对账含税单价", dto.getAsTaxPrice().toString());
            map.put("对账未税金额", dto.getAsNotTaxAmount().toString());
            map.put("对账含税金额", dto.getAsTaxAmount().toString());
            map.put("对账税率", dto.getAsTaxCode() + "(" + dto.getAsTaxValue() + "%)");
            map.put("对账税额", dto.getAsDiffTaxAmount().toString());
            map.put("入库凭证", dto.getReceiveCode() + "#" + dto.getReceiveRowNo());
            map.put("入库时间", dto.getReceiveDate() == null ? "" : DateUtil.format(dto.getReceiveDate(), "yyyy-MM-dd HH:mm:ss"));
            map.put("物料编码", dto.getMaterialCode());
            map.put("物料名称", dto.getMaterialName());
            map.put("单位", dto.getMaterialUnit());
            map.put("SAP订单号", dto.getPoCode());
            map.put("订单行号", dto.getPoItemNo());
//            map.put("询源采购组", "(" + dto.getSeekPgCode() + ")" + dto.getSeekPgName());
//            map.put("订单税率", dto.getPoTaxCode() + "(" + dto.getPoTaxValue() + "%)");
//            map.put("付款方式", "(" + dto.getPaymentWayCode() + ")" + dto.getPaymentWayDesc());
            map.put("付款条件", "(" + dto.getPaymentTermCode() + ")" + dto.getPaymentTermName());
//            map.put("原材料商", "(" + dto.getMaterialSupplierCode() + ")" + dto.getMaterialSupplierName());
            result.add(map);
        }

        return result;
    }

    /**
     * 处理开票申请单主表数据
     *
     * @param head      开票申请单主表数据
     * @param dataIndex 当前从哪行写入
     * @param workbook  工作簿
     * @param sheet     工作簿中的表
     * @param cellStyle 单元格样式
     * @return 结果 已使用到表格那一行
     */
    private Integer handleTableHeadData(InvoicedApply head, Integer dataIndex, XSSFWorkbook workbook, XSSFSheet sheet, XSSFCellStyle cellStyle) {
        // 将图片插入Excel中
        String picturePath = "F:/微信图片_20200819214941.png";
        EasyExcelUtils.insertPatriarch(workbook, sheet, picturePath);

        XSSFRow headRow = sheet.createRow(dataIndex);
        XSSFCell headRowCell1 = headRow.createCell(0);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex + 4, 0, 4));
        headRowCell1.setCellValue("");

        XSSFCell headRowCell2 = headRow.createCell(5);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex + 4, 5, 17));
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headRowCell2.setCellValue("开票申请");
        // 设置字体
        Font cellFont = workbook.createFont();
        cellFont.setFontName("宋体");
        cellFont.setFontHeight((short) (15 * 20));
        cellStyle.setFont(cellFont);
        headRowCell2.setCellStyle(cellStyle);


        dataIndex += dataIndex + 5;
        // 主表数据第一行 供应商、采购公司、创建日期
        XSSFRow headRow1 = sheet.createRow(dataIndex);
        headRow1.setHeight((short) (25 * 20));
        XSSFCell headRow1Cell1 = headRow1.createCell(0);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 1));
        headRow1Cell1.setCellValue("供应商:");

        XSSFCell headRow1Cell2 = headRow1.createCell(2);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 2, 5));
        headRow1Cell2.setCellValue("(" + head.getSupplierCode() + ")" + head.getSupplierName());

        XSSFCell headRow1Cell3 = headRow1.createCell(6);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 6, 7));
        headRow1Cell3.setCellValue("采购公司: ");

        XSSFCell headRow1Cell4 = headRow1.createCell(8);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 8, 11));
        headRow1Cell4.setCellValue("(" + head.getCompanyCode() + ")" + head.getCompanyName());

        XSSFCell headRow1Cell5 = headRow1.createCell(12);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 12, 13));
        headRow1Cell5.setCellValue("创建日期: ");

        XSSFCell headRow1Cell6 = headRow1.createCell(14);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 14, 17));
        headRow1Cell6.setCellValue(DateUtil.format(head.getCreateTime(), "yyyy/MM/dd HH:mm:ss"));

        dataIndex += 1;
        // 主表数据第二行 到票未税金额、到票含税金额、到票税额
        XSSFRow headRow2 = sheet.createRow(dataIndex);
        headRow2.setHeight((short) (25 * 20));
        XSSFCell headRow2Cell1 = headRow2.createCell(0);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 1));
        headRow2Cell1.setCellValue("到票未税金额:");

        XSSFCell headRow2Cell2 = headRow2.createCell(2);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 2, 5));
        headRow2Cell2.setCellValue(head.getInvoiceNetAmount().toString());

        XSSFCell headRow2Cell3 = headRow2.createCell(6);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 6, 7));
        headRow2Cell3.setCellValue("到票含税金额: ");

        XSSFCell headRow2Cell4 = headRow2.createCell(8);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 8, 11));
        headRow2Cell4.setCellValue(head.getInvoiceTaxAmount().toString());

        XSSFCell headRow2Cell5 = headRow2.createCell(12);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 12, 13));
        headRow2Cell5.setCellValue("到票税额: ");

        XSSFCell headRow2Cell6 = headRow2.createCell(14);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 14, 17));
        headRow2Cell6.setCellValue(head.getInvoiceDiffAmount().toString());


        dataIndex += 1;
        // 主表数据第四行 发票号
        XSSFRow headRow4 = sheet.createRow(dataIndex);
        headRow4.setHeight((short) (25 * 20));
        XSSFCell headRow4Cell1 = headRow4.createCell(0);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 0, 1));
        headRow4Cell1.setCellValue("发票号:");

        XSSFCell headRow4Cell2 = headRow4.createCell(2);
        sheet.addMergedRegion(new CellRangeAddress(dataIndex, dataIndex, 2, 5));
        headRow4Cell2.setCellValue(head.getInvoiceNo());

        return dataIndex;
    }


    public void financeConfirm(InvoicedApply head, String approveRemark, Integer approveStatus, CurrentUserDTO user,List<AttachmentManualCheck> manualCheckList) {
        InvoicedApply updateHead = new InvoicedApply();
        updateHead.setId(head.getId());
        updateHead.setRemark(head.getRemark());
        updateHead.setUpdateTime(LocalDateTime.now());
        updateHead.setUpdateUserId(user.getUserId());
        updateHead.setUpdateUserCode(user.getLoginName());
        updateHead.setUpdateUserName(user.getName());

        // 数据状态 1:暂存发票 2:待采购确认发票 3:采购拒绝发票 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认发票 8:财务驳回发票 9:发票已确认
        if (1 == approveStatus) {
            //查询发票
            List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(new LambdaQueryWrapper<>(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, head.getId()));
            if (CollUtil.isNotEmpty(invoicedReceipts)) {
                //提取serialNo不为空的数据为list<String>
                List<String> serialNoList = invoicedReceipts.stream()
                        .map(InvoicedReceipt::getSerialNo)
                        .filter(StrUtil::isNotEmpty)
                        .toList();
                if (CollUtil.isNotEmpty(serialNoList)) {
                    kingdeeInvoiceCloudLogic.billSign(String.valueOf(head.getId()), "01", String.join(",", serialNoList));
                }
            }
            updateHead.setFinanceConfirmTime(LocalDateTime.now());
            updateHead.setFinanceConfirmUserId(LoginUtil.getUserId());
            updateHead.setStatus(9);
            updateHead.setPostStatus(2);
            InvoicedApply old = invoicedApplyService.getById(head.getId());
            //美金对账单，到票申请交接-财务确认后，无需“财务过账”
            if (!"CNY".equals(old.getCurrencyCode()) || old.getForeignCurrencyAddFlag() == 1) {
                updateHead.setPostStatus(6);
            }
            this.updatePurchaseOrderFin(JSONArray.toJSONString(ListUtil.toList( head.getId())));
            try {
                this.payableSend(JSONArray.toJSONString(ListUtil.toList( head.getId())));
            } catch (Exception ignored) {}


        } else {
            updateHead.setStatus(8);
            updateHead.setPostStatus(1);
            //删除影像化
            this.deleteImg(head.getId());
            this.deleteAllImg(head.getId());
            //查询已经关联预付款数据，如果有就减去上次冲账金额且删除
            List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, head.getId()));
            if (CollectionUtils.isNotEmpty(invoicedApplyPaList)) {
                List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
                invoicedApplyPaList.forEach(ipa -> {
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());

                    //2025-09-03增加如果开票申请关联的预付款申请单上关联了变更单，则不更新该条预付款已冲账金额
                    if (StringUtils.isEmpty(ipa.getPaymentChangeNumber()) && StringUtils.isEmpty(ipa.getPaymentChangeItemNo())) {
                        if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                            paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()).compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()));
                        }
                    } else {
                        String paymentChangeNumber = ipa.getPaymentChangeNumber();
                        String paymentChangeItemNo = ipa.getPaymentChangeItemNo();
                        if (StringUtils.isNotEmpty(paymentChangeNumber) && StringUtils.isNotEmpty(paymentChangeItemNo)) {
                            //页面预付款明细为空，数据库有关联预付款变更单需要更新已冲账金额
                            paymentAdvanceApplyDetailLogic.updateReversedAmount(paymentChangeNumber, paymentChangeItemNo, ipa.getStrikePrice().negate());
                        }
                    }
                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)) {
                        paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                    }
                });
                if (CollectionUtils.isNotEmpty(paymentAdvanceApplyDetailList)) {
                    paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList);
                }
                invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId, head.getId()));
            }
            InvoicedApply invoicedApply = invoicedApplyService.getById(head.getId());
            //1，财务驳回发票交接，增加邮件提醒，  邮件收件人：供应商（(4)财务人员、(12)业务接口人、(5)业务经理）、对账采购组窗口
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailBis.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), approveRemark);
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailFin.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), approveRemark);
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailJl.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), approveRemark);
            }
        }
        if (CollUtil.isNotEmpty(manualCheckList)){
            manualCheckList.forEach(manualCheck -> {
                if (manualCheck.getId() == null){
                    manualCheck.setCreateUser(LoginUtil.getUserId());
                    manualCheck.setCreateTime(LocalDateTime.now());
                }else {
                    manualCheck.setUpdateUser(LoginUtil.getUserId());
                    manualCheck.setUpdateTime(LocalDateTime.now());
                }
            });
            attachmentManualCheckService.saveOrUpdateBatch(manualCheckList);
        }
        if (!invoicedApplyService.updateById(updateHead)) {
            throw new DaoException("更新对账单主表数据失败, 请联系管理员");
        }


        if (!invoicedApplyApproveLogic.addApproveRecord(head.getId(), head.getInvoiceApplyNo(), approveStatus, approveRemark, 2, user)) {
            throw new DaoException("添加开票申请单审批记录失败, 请联系管理员");
        }

        // 财务通过后, 生成SRM开票申请过账数据
        if (2 == updateHead.getPostStatus()) {
            InvoicedApplyPostResult pr1 = new InvoicedApplyPostResult();
            pr1.setCreateTime(LocalDateTime.now());
            pr1.setInvoiceApplyId(head.getId());
            pr1.setInvoiceApplyNo(head.getInvoiceApplyNo());
            //查找不包含贷项的凭证 161 162
            List<InvoicedApplyDetail> details = invoicedApplyDetailLogic.findByInvoiceNo(head.getInvoiceApplyNo());
            if (CollectionUtils.isNotEmpty(details)) {
                // 凭证发票
                pr1.setPostInvoiceType(1);
            } else {
                // 贷项凭证
                pr1.setPostInvoiceType(4);
            }
            if (!invoicedApplyPostResultService.save(pr1)) {
                throw new DaoException("添加开票申请单待过账记录失败, 请联系管理员");
            }
            InvoicedApply invoicedApply = invoicedApplyService.getById(head.getId());
            //异步邮件通知 供应商 12业务接口人 4财务人员 2024-11-13 邓京术
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailBis.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), "");
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailFin.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), "");
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailJl.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(), "");
            }
        }
    }

    /**
     * 采购确认开票申请
     *
     * @param head          变更的开票申请表头数据
     * @param detailList    新增的开票申请明细
     * @param delDidList    待删除的开票申请明细ID集合
     * @param delSdIdList   待删除的开票申请扣款记录ID集合
     * @param delSrIdList   待删除的开票申请返利记录ID集合
     * @param addSdIdList   待删除的开票申请扣款记录ID
     * @param addSrIdList   待删除的开票申请返利记录ID
     * @param approveRemark 审批备注
     * @param approveStatus 确认结果 0:拒绝 1:通过
     * @param user          当前操作人
     */
    private void purchaseConfirm(
            InvoicedApply head, List<InvoicedApplyItemDTO> detailList, List<Long> delDidList, List<Long> delSdIdList,
            List<Long> delSrIdList, List<Long> addSdIdList, List<Long> addSrIdList, String approveRemark, Integer approveStatus,
            CurrentUserDTO user,List<AttachmentManualCheck> manualCheckList
    ) {
        // 保存开票申请单审批确认记录
        if (!invoicedApplyApproveLogic.addApproveRecord(head.getId(), head.getInvoiceApplyNo(), approveStatus, approveRemark, 1, user)) {
            throw new DaoException("添加开票申请单审批记录失败, 请联系管理员");
        }

        if (1 == approveStatus) {
            head.setStatus(7);
            //计算开票税额
            head.setInvoiceDiffAmount(head.getInvoiceTaxAmount().subtract(head.getInvoiceNetAmount()));
            // 先变更开票申请相关数据
//            this.dataEdit(head, detailList, delDidList, delSdIdList, delSrIdList, addSdIdList, addSrIdList,null, user);

            // 开票申请单采购确认出现总金额差异超过±1 则需要推送OA审批
//            BigDecimal diffAmount = BigDecimal.ZERO;
//            for (InvoicedApplyItemDto dto : detailList) {
//                diffAmount = dto.getIaDiffAmount().add(diffAmount);
//            }
//
//            // 默认单价差异范围
//            BigDecimal difRang = BigDecimal.ONE;
//            // 获取字典配置中的单价差异范围
//            final DictItemDto item = dictService.getDictDataByTypeAndItemCode("statement_invoiced_difference", "invoiced_difference_amount");
//            if (null != item) {
//                difRang = new BigDecimal(item.getItemDescription());
//            }
//
//            // 采购确认后需要推送OA审批
//            if (diffAmount.abs().compareTo(difRang) >= 0) {
//                final OaReturnResult result = this.invoicedApplyPushOa(head, detailList, diffAmount, user);
//                if (0 == result.getCode()) {
//                    // 数据状态 1:暂存发票 2:待采购确认发票 3:采购拒绝发票 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认发票 8:财务驳回发票 9:发票已确认
//                    head.setStatus(5);
//                    head.setOaProcessNo(result.getData());
//                    head.setPushOaNum(head.getPushOaNum() + 1);
//                    head.setPushOaUserCode(user.getLoginName());
//                    head.setPushOaUserName(user.getName());
//                } else {
//                    head.setStatus(4);
//                }
//            }

            // 开票申请表头添加采购确认人相关信息
            head.setPcTime(LocalDateTime.now());
            head.setPcUserId(user.getUserId());
            head.setPcUserCode(user.getLoginName());
            head.setPcUserName(user.getName());

            if ("CNY".equals(head.getCurrencyCode())) {
                head.setActualUnpaidAmount(head.getInvoiceTaxTotalAmount().subtract(head.getStrikePriceAmount() == null ? BigDecimal.ZERO : head.getStrikePriceAmount()));
            } else {
                head.setActualUnpaidAmount(head.getInvoiceTaxAmount().subtract(head.getStrikePriceAmount() == null ? BigDecimal.ZERO : head.getStrikePriceAmount()));
            }

            //判断是否有签署附件
            Boolean su = eSignClient.checkList(head.getAccountStatementId());

            if (head.getActualUnpaidAmount() == null) {
                throw new DaoException("实际未付金额不能为空");
            }

            if (head.getActualUnpaidAmount().compareTo(BigDecimal.ZERO) != 0) {
                if (head.getPaperlessFlag() == 1 && !su) {
                    throw new DaoException("请签署电子签章");
                }
            }


            //影像化
            this.toImg(head.getId());
            this.toAllImg(head.getId());

        } else {
            head.setStatus(3);

            this.deleteImg(head.getId());
            this.deleteAllImg(head.getId());

//            attachmentManualCheckService.remove(new LambdaQueryWrapper<AttachmentManualCheck>()
//                    .eq(AttachmentManualCheck::getBusinessType,1)
//                    .eq(AttachmentManualCheck::getBusinessId,head.getId())
//            );
        }
        if (CollUtil.isNotEmpty(manualCheckList)){
            manualCheckList.forEach(manualCheck -> {
                if (manualCheck.getId() == null){
                    manualCheck.setCreateUser(LoginUtil.getUserId());
                    manualCheck.setCreateTime(LocalDateTime.now());
                }else {
                    manualCheck.setUpdateUser(LoginUtil.getUserId());
                    manualCheck.setUpdateTime(LocalDateTime.now());
                }
            });
            attachmentManualCheckService.saveOrUpdateBatch(manualCheckList);
        }
        if (!invoicedApplyService.updateById(head)) {
            throw new DaoException("更新开票申请表头数据失败, 前联系管理员");
        }

        // 采购到票确认后状态变更为7, 则清空OA相关字段值
        if (7 == head.getStatus()) {
            InvoicedApply oldHead = invoicedApplyService.getById(head.getId());
            oldHead.setPushOaUserCode(null);
            oldHead.setUpdateUserName(null);
            oldHead.setPushOaNum(0);
            oldHead.setOaProcessId(null);
            oldHead.setOaProcessNo(null);
            invoicedApplyService.updateById(oldHead);
        }
    }
    @Override
    public void revokeFinConfirmOld(Long iaId, String revokeReason) {
        if (null == iaId) {
            throw new DaoException("参数错误");
        }
        final InvoicedApply apply = invoicedApplyService.getById(iaId);
        if (null == apply) {
            throw new DaoException("系统未找到相应的开票申请信息");
        }
        if (7 != apply.getStatus()) {
            throw new DaoException("开票申请不能进行撤销操作, 请检查开票申请状态");
        }

        InvoicedApply updateHead = new InvoicedApply();
        updateHead.setId(apply.getId());
        updateHead.setStatus(2);
        updateHead.setUpdateUserId(LoginUtil.getUserId());
        updateHead.setUpdateUserCode(LoginUtil.getAccount());
        updateHead.setUpdateUserName(LoginUtil.getName());
        updateHead.setUpdateTime(LocalDateTime.now());
        invoicedApplyService.updateById(updateHead);

        //查询已经关联预付款数据，如果有就减去上次冲账金额且删除
        List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,apply.getId()));
        if (CollectionUtils.isNotEmpty(invoicedApplyPaList)){
            List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
            invoicedApplyPaList.forEach(ipa->{
                PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());
                if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)){
                    paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()).compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()));
                    paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                }
            });
            paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList);
            invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,apply.getId()));
        }

        // 2.记录撤销原因
        InvoicedApplyApprove approve = new InvoicedApplyApprove();
        approve.setIaId(apply.getId());
        approve.setIaNo(apply.getInvoiceApplyNo());
        approve.setApproveResult(2);
        approve.setApproveOpinion(revokeReason);
        approve.setApproveUserId(LoginUtil.getUserId());
        approve.setApproveUserCode(LoginUtil.getAccount());
        approve.setApproveUserName(LoginUtil.getName());
        // 撤销只能由采购操作
        approve.setApproveNode(1);
        approve.setApproveTime(LocalDateTime.now());
        invoicedApplyApproveService.save(approve);
    }

    /**
     * 影像化
     *
     * @param iaId 开票申请ID
     */
    @Override
    public void toImg(Long iaId) {
        InvoicedApply invoicedApply = invoicedApplyService.getById(iaId);
        //影像化
        List<BusinessAttachmentDTO> accountStatementAttachments = this.getImgList(iaId);
        if (CollUtil.isNotEmpty(accountStatementAttachments)) {
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(StrUtil.isNotEmpty(invoicedApply.getImgCode()) ? invoicedApply.getImgCode() : sequenceClient.createSequenceNo("image_code"));
            if (CollUtil.isNotEmpty(accountStatementAttachments)) {
                kingdeeInvoiceCloudImageDTO.setBusinessAttachmentList(accountStatementAttachments);
                KingdeeInvoiceCloudImageDTO result = kingdeeImageLogic.pushImage(kingdeeInvoiceCloudImageDTO);
                //更新签署附件的影像
                accountStatementAttachments.forEach(businessAttachmentDTO -> {
                    if (businessAttachmentDTO.getType().equals("account")) {
                        digitalSealBusinessDetailService.update(new LambdaUpdateWrapper<DigitalSealBusinessDetail>()
                                .set(DigitalSealBusinessDetail::getImageCode, result.getImageCode())
                                .set(DigitalSealBusinessDetail::getImagePath, result.getImagePath())
                                .set(DigitalSealBusinessDetail::getImageFileId, businessAttachmentDTO.getImageFileId())
                                .eq(DigitalSealBusinessDetail::getId, businessAttachmentDTO.getFileId()));
                    }
                });
                //发票附件的影像
                accountStatementAttachments.forEach(businessAttachmentDTO -> {
                    if (businessAttachmentDTO.getType().equals("invoice")) {
                        attachmentService.update(new LambdaUpdateWrapper<Attachment>()
                                .set(Attachment::getImageCode, result.getImageCode())
                                .set(Attachment::getImagePath, result.getImagePath())
                                .set(Attachment::getImageFileId, businessAttachmentDTO.getImageFileId())
                                .eq(Attachment::getId, businessAttachmentDTO.getFileId()));
                    }
                });
                invoicedApplyService.update(new LambdaUpdateWrapper<InvoicedApply>().set(InvoicedApply::getImgCode, result.getImageCode()).set(InvoicedApply::getImgTime, LocalDateTime.now()).set(InvoicedApply::getImgUserId, LoginUtil.getUserId())
                        .eq(InvoicedApply::getId, iaId));
            }

        }
    }

    @Override
    public String toAllImg(Long iaId) {
        InvoicedApply invoicedApply = invoicedApplyService.getById(iaId);
        //影像化
        List<BusinessAttachmentDTO> accountStatementAttachments = this.getImgList(iaId);
        accountStatementAttachments.addAll(accountStatementLogic.getImgList(invoicedApply.getAccountStatementId()));
        //accountStatementAttachments中按照sort从小到大排序
        accountStatementAttachments.sort(
                Comparator.nullsLast(Comparator.comparing(BusinessAttachmentDTO::getSort)));
        if (CollUtil.isNotEmpty(accountStatementAttachments)) {
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(StrUtil.isNotEmpty(invoicedApply.getImgAllCode()) ? invoicedApply.getImgAllCode() : sequenceClient.createSequenceNo("image_code"));
            if (CollUtil.isNotEmpty(accountStatementAttachments)) {
                kingdeeInvoiceCloudImageDTO.setBusinessAttachmentList(accountStatementAttachments);
                KingdeeInvoiceCloudImageDTO result = kingdeeImageLogic.pushImage(kingdeeInvoiceCloudImageDTO);
                invoicedApplyService.update(new LambdaUpdateWrapper<InvoicedApply>().set(InvoicedApply::getImgAllCode, result.getImageCode()).set(InvoicedApply::getImgTime, LocalDateTime.now()).set(InvoicedApply::getImgUserId, LoginUtil.getUserId())
                        .eq(InvoicedApply::getId, iaId));
                return result.getImageCode();
            }

        }
        return "";
    }

    @Override
    public List<BusinessAttachmentDTO>  getImgList(Long id) {
        InvoicedApply invoicedApply = invoicedApplyService.getById(id);
        //影像化
        List<BusinessAttachmentDTO> accountStatementAttachments = businessAttachmentLogic.getListByBusinessId(id);
        //获取对账单签署附件
        List<DigitalSealBusinessDetailDTO> digitalSealBusinessDetailDTOS = eSignLogic.fileList(invoicedApply.getAccountStatementId(), "account_statement,purchase_sale_contract,purchase_sale_process_contract", "1,2",1);
        if (CollUtil.isNotEmpty(digitalSealBusinessDetailDTOS)) {
            DictDTO dictDTO = dictClient.getDictByTypeAndCode("businessFileType", "account");
            digitalSealBusinessDetailDTOS.forEach(digitalSealBusinessDetailDTO -> {
                BusinessAttachmentDTO businessAttachmentDTO = new BusinessAttachmentDTO();
                Attachment attachment = attachmentService.getById(digitalSealBusinessDetailDTO.getFileId());
                businessAttachmentDTO.setFileName(attachment.getFileName());
                businessAttachmentDTO.setBusinessId(id);
                businessAttachmentDTO.setType("account");
                businessAttachmentDTO.setBusinessTypeCode("account_statement");
                businessAttachmentDTO.setSort(ObjectUtil.isNotNull(dictDTO)?dictDTO.getSort():null);
                businessAttachmentDTO.setImageFileId(digitalSealBusinessDetailDTO.getImageFileId());
                businessAttachmentDTO.setImageCode(digitalSealBusinessDetailDTO.getImageCode());
                businessAttachmentDTO.setFileId(digitalSealBusinessDetailDTO.getFileId());
                accountStatementAttachments.add(businessAttachmentDTO);
            });
        }
        //获取发票附件
        List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(Wrappers.lambdaQuery(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, id));
        if (CollUtil.isNotEmpty(invoicedReceipts)){
            //提取invoicedReceipts中的附件id
            List<Long> invoicedReceiptFileIds = invoicedReceipts.stream().map(InvoicedReceipt::getFileId).collect(Collectors.toList());
            List<FileResposeCDTO> fileResposeCDTOList = fileClient.getFileInfos(invoicedReceiptFileIds);
            if (CollUtil.isNotEmpty(fileResposeCDTOList)){
                DictDTO dictDTO = dictClient.getDictByTypeAndCode("businessFileType", "invoice");
                fileResposeCDTOList.forEach(file -> {
                    BusinessAttachmentDTO businessAttachmentDTO = new BusinessAttachmentDTO();
                    businessAttachmentDTO.setFileId(file.getId());
                    businessAttachmentDTO.setImageFileId(file.getImageFileId());
                    businessAttachmentDTO.setType("invoice");
                    businessAttachmentDTO.setFileName(file.getFileName());
                    businessAttachmentDTO.setSort(ObjectUtil.isNotNull(dictDTO)?dictDTO.getSort():null);
                    accountStatementAttachments.add(businessAttachmentDTO);
                });
            }
        }
        //accountStatementAttachments中按照sort从小到大排序
        accountStatementAttachments.sort(
                Comparator.nullsLast(Comparator.comparing(BusinessAttachmentDTO::getSort)));

        return accountStatementAttachments;
    }

    /**
     * 删除影像化
     *
     * @param iaId 开票申请ID
     */
    @Override
    public void deleteImg(Long iaId) {
        //删除影像化
        InvoicedApply invoicedApply = invoicedApplyService.getById(iaId);
        if (ObjectUtil.isEmpty(invoicedApply.getImgTime())){
            return;
        }
        List<BusinessAttachment> businessAttachments = businessAttachmentService.list(new LambdaQueryWrapper<BusinessAttachment>().eq(BusinessAttachment::getBusinessId, iaId));
        //获取对账单签署附件
        List<DigitalSealBusinessDetailDTO> digitalSealBusinessDetailDTOS = eSignLogic.fileList(invoicedApply.getAccountStatementId(), "account_statement,purchase_sale_contract,purchase_sale_process_contract", "1,2",null);
        if (CollUtil.isNotEmpty(digitalSealBusinessDetailDTOS)) {
            digitalSealBusinessDetailDTOS.forEach(digitalSealBusinessDetailDTO -> {
                BusinessAttachment businessAttachmentDTO = new BusinessAttachment();
                businessAttachmentDTO.setBusinessId(iaId);
                businessAttachmentDTO.setBusinessTypeCode("account_statement");
                businessAttachmentDTO.setImageFileId(digitalSealBusinessDetailDTO.getImageFileId());
                businessAttachmentDTO.setImageCode(digitalSealBusinessDetailDTO.getImageCode());
                businessAttachmentDTO.setFileId(digitalSealBusinessDetailDTO.getFileId());
                businessAttachments.add(businessAttachmentDTO);
            });
        }
        //获取发票附件
        List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(Wrappers.lambdaQuery(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, iaId));
        List<BusinessAttachment> invoicedReceiptFiles = new ArrayList<>();
        if (CollUtil.isNotEmpty(invoicedReceipts)){
            //提取invoicedReceipts中的附件id
            List<Long> invoicedReceiptFileIds = invoicedReceipts.stream().map(InvoicedReceipt::getFileId).collect(Collectors.toList());
            List<FileResposeCDTO> fileResposeCDTOList = fileClient.getFileInfos(invoicedReceiptFileIds);
            if (CollUtil.isNotEmpty(fileResposeCDTOList)){
                fileResposeCDTOList.forEach(file -> {
                    BusinessAttachment businessAttachmentDTO = new BusinessAttachment();
                    businessAttachmentDTO.setBusinessId(iaId);
                    businessAttachmentDTO.setBusinessTypeCode("invoice_apply");
                    businessAttachmentDTO.setImageFileId(file.getImageFileId());
                    businessAttachmentDTO.setImageCode(file.getImageCode());
                    businessAttachmentDTO.setFileId(file.getId());
                    businessAttachments.add(businessAttachmentDTO);
                    invoicedReceiptFiles.add(businessAttachmentDTO);
                });
            }

        }
        KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
        kingdeeInvoiceCloudImageDTO.setImageCode(invoicedApply.getImgCode());
        kingdeeImageLogic.deleteAllImage(kingdeeInvoiceCloudImageDTO);
        invoicedApplyService.update(new LambdaUpdateWrapper<InvoicedApply>()
//                        .set(InvoicedApply::getImgCode,null)
                .set(InvoicedApply::getImgAllCode, null)
                .set(InvoicedApply::getImgTime, null)
                .set(InvoicedApply::getImgUserId, null)
                .eq(InvoicedApply::getId, iaId));
        if (CollUtil.isNotEmpty(digitalSealBusinessDetailDTOS)) {
            digitalSealBusinessDetailDTOS.forEach(digitalSealBusinessDetailDTO -> {
                digitalSealBusinessDetailService.update(new LambdaUpdateWrapper<DigitalSealBusinessDetail>()
                        .set(DigitalSealBusinessDetail::getImageCode, null)
                        .set(DigitalSealBusinessDetail::getImagePath, null)
                        .set(DigitalSealBusinessDetail::getImageFileId, null)
                        .eq(DigitalSealBusinessDetail::getId, digitalSealBusinessDetailDTO.getId()));
            });
        }
    }

    @Override
    public void deleteAllImg(Long iaId) {
        //删除影像化
        InvoicedApply invoicedApply = invoicedApplyService.getById(iaId);
        if (StrUtil.isEmpty(invoicedApply.getImgAllCode())){
            return;
        }
        KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
        kingdeeInvoiceCloudImageDTO.setImageCode(invoicedApply.getImgAllCode());
        kingdeeImageLogic.deleteAllImage(kingdeeInvoiceCloudImageDTO);
    }

    /**
     * 开票申请编辑是保存数据
     *
     * @param head        变更的开票申请表头数据
     * @param detailList  新增的开票申请明细
     * @param delDidList  待删除的开票申请明细ID集合
     * @param delSdIdList 待删除的开票申请扣款记录ID集合
     * @param delSrIdList 待删除的开票申请返利记录ID集合
     * @param addSdIdList 待删除的开票申请扣款记录ID
     * @param addSrIdList 待删除的开票申请返利记录ID
     * @param user        当前操作人
     */
    public void dataEdit(
            InvoicedApply head, List<InvoicedApplyItemDTO> detailList, List<Long> delDidList, List<Long> delSdIdList,
            List<Long> delSrIdList, List<Long> addSdIdList, List<Long> addSrIdList, List<Long> addPaIds, CurrentUserDTO user
    ) {
        head.setUpdateTime(LocalDateTime.now());
        head.setUpdateUserId(user.getUserId());
        head.setUpdateUserCode(user.getLoginName());
        head.setUpdateUserName(user.getName());
        if (!invoicedApplyService.updateById(head)) {
            throw new DaoException("保存开票申请表头数据失败, 前联系管理员");
        }

        // 开票申请单采购确认出现总金额差异超过±1 则需要推送OA审批
        BigDecimal diffAmount = BigDecimal.ZERO;
        List<InvoicedApplyDetail> iadList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(detailList)) {

            for (InvoicedApplyItemDTO dto : detailList) {
                InvoicedApplyDetail iad = dto.toIad();
                if (0 == dto.getId()) {
                    iad.setCreateUserId(user.getUserId());
                    iad.setCreateUserCode(user.getLoginName());
                    iad.setCreateUserName(user.getName());
                    iad.setCreateTime(LocalDateTime.now());
                    iad.setId(null);
                } else {
                    iad.setUpdateUserId(user.getUserId());
                    iad.setUpdateUserCode(user.getLoginName());
                    iad.setUpdateUserName(user.getName());
                    iad.setUpdateTime(LocalDateTime.now());
                }

                diffAmount = dto.getIaDiffAmount().add(diffAmount);
                iadList.add(iad);
            }
        }


        // 校验开票明细中反向凭证对应的正向是否也在其中
        final String checkResult = this.checkInvoicedApplyDetail(head.getSupplierCode(), iadList, head.getOrderType());
        if (StringUtils.isNotEmpty(checkResult)) {
            throw new DaoException(checkResult);
        }

        if (CollectionUtils.isNotEmpty(iadList)) {
            if (!invoicedApplyDetailService.saveOrUpdateBatch(iadList)) {
                throw new DaoException("保存开票申请明细数据失败, 请联系管理员");
            }
        }

        if (CollectionUtils.isNotEmpty(delDidList)) {
            List<InvoicedApplyDetail> delDetailList = Lists.newArrayList();
            for (Long did : delDidList) {
                InvoicedApplyDetail iad = new InvoicedApplyDetail();
                iad.setId(did);
                iad.setDeleteFlag(1);
                iad.setItemNo("000000");
                iad.setUpdateTime(LocalDateTime.now());
                iad.setUpdateUserId(user.getUserId());
                iad.setUpdateUserCode(user.getLoginName());
                iad.setUpdateUserName(user.getName());
                delDetailList.add(iad);
            }
            if (!invoicedApplyDetailService.updateBatchById(delDetailList)) {
                throw new DaoException("删除开票申请明细数据失败, 前联系管理员");
            }
        }

        // 删除开票申请对应的扣款和返利记录
//        this.delSdAndSr(delSdIdList, delSrIdList);
//        this.delPa(head,addPaIds);
//
//        // 添加开票申请对应的扣款和返利
//        this.addSdAndSr(head, addSdIdList, addSrIdList);
//        this.addPa(head, addPaIds);

        // 开票完成
        List<Long> asdIdList1 = Lists.newArrayList();
        for (InvoicedApplyDetail detail : iadList) {
            asdIdList1.add(detail.getAsdId());
        }
        accountStatementLogic.updateInvoiceCompleteFlag(asdIdList1, 1);

        // 开票未完成
        if (CollectionUtils.isNotEmpty(delDidList)) {
            List<InvoicedApplyDetail> delIadList = invoicedApplyDetailService.findByIdList(delDidList);
            List<Long> asdIdList2 = Lists.newArrayList();
            for (InvoicedApplyDetail delIad : delIadList) {
                if (1 == delIad.getDeleteFlag()) {
                    asdIdList2.add(delIad.getAsdId());
                }
            }
            accountStatementLogic.updateInvoiceCompleteFlag(asdIdList2, 0);
        }

        // 重新生成开票明细的行号
        invoicedApplyDetailLogic.updateDetailItemNo(head.getId());
    }

    /**
     * 检查开票申请单中，是否已经存在已经财务确认发票且未删除的对账单
     *
     * @param invoicedApplyStatementNo
     * @return
     */
    public InvoicedApply findInvoicedApplyByStatementNo(String invoicedApplyStatementNo) {
        InvoicedApply invoicedApply = invoicedApplyService.getOne(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getAccountStatementNo, invoicedApplyStatementNo)
                .eq(InvoicedApply::getStatus, 9)
                .eq(InvoicedApply::getDeleteFlag, "0")
                .last(" limit 1"));
        return invoicedApply;
    }
    public InvoicedApply findInvoicedExtApplyByStatementNo(String invoicedApplyStatementNo) {
        InvoicedApply invoicedApply = invoicedApplyService.getOne(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getAccountStatementNo, invoicedApplyStatementNo)
                .eq(InvoicedApply::getDeleteFlag, "0")
                .last(" limit 1"));
        return invoicedApply;
    }

    @Override
    public void updatePostStatus(Long iaId, Integer postStatus) {
        InvoicedApply invoicedApply = new InvoicedApply();
        invoicedApply.setId(iaId);
        invoicedApply.setPostStatus(postStatus);
        invoicedApplyService.updateById(invoicedApply);
    }

    @Override
    public void updateContractSupplementStatus(Long iaId, Integer contractSupplementStatus) {
        InvoicedApply invoicedApply = new InvoicedApply();
        invoicedApply.setId(iaId);
        invoicedApply.setContractSupplementStatus(contractSupplementStatus);
        invoicedApplyService.updateById(invoicedApply);
    }

    @Override
    public Boolean statementInvoicingCheck(String statementNo) {
        List<InvoicedApply> list = invoicedApplyService.list(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getAccountStatementNo, statementNo).ne(InvoicedApply::getDeleteFlag, 1));
        if (CollectionUtils.isNotEmpty(list)) {
            return true;
        }
        return false;
    }

    /**
     * 红冲
     *
     * @param params
     */
    @Override
    @Transactional
    public void redReversal(InvoicedRedReversalParamDTO params) {
        InvoicedApply head = invoicedApplyService.getById(params.getId());
        if (head.getRedReversalStatus() != 0 && head.getRedReversalStatus() != 1) {
            throw new DaoException("选中的开票申请存在数据状态不支持红冲操作, 请检查");
        }
        if (head.getForeignCurrencyAddFlag() == 1) {
            throw new DaoException("选中的开票申请为外币资料交接，不支持红冲操作");
        }
        head.setRedReversalStatus(CollUtil.isNotEmpty(params.getInvoiceSelectList()) ? 1 : 0);
        head.setRedReversalReason(params.getRedReversalReason());
        invoicedApplyService.updateById(head);
        //先取消所有的红冲
        invoicedReceiptService.update(new LambdaUpdateWrapper<InvoicedReceipt>()
                .set(InvoicedReceipt::getDeductionStatus, 2)
//                .set(InvoicedReceipt::getDeleteFlag, 0)
                .eq(InvoicedReceipt::getIaId, head.getId()));
        //添加
        if (CollUtil.isNotEmpty(params.getInvoiceSelectList())) {
            //把旧的发票数据打上不可删除的标记
            invoicedReceiptService.update(new LambdaUpdateWrapper<InvoicedReceipt>()
                    .set(InvoicedReceipt::getNotDeleteFlag, 1)
                    .eq(InvoicedReceipt::getIaId, head.getId()));

            invoicedReceiptService.update(new LambdaUpdateWrapper<InvoicedReceipt>()
                    .set(InvoicedReceipt::getDeductionStatus, 3)
//                    .set(InvoicedReceipt::getDeleteFlag, 1)
                    .eq(InvoicedReceipt::getIaId, head.getId())
                    .in(InvoicedReceipt::getId, params.getInvoiceSelectList().stream().map(InvoicedReceiptDTO::getId).collect(Collectors.toList())));


            //查询发票
            List<InvoicedReceipt> invoicedReceipts = invoicedReceiptService.list(new LambdaQueryWrapper<>(InvoicedReceipt.class).eq(InvoicedReceipt::getIaId, head.getId()).eq(InvoicedReceipt::getDeductionStatus, 3));
            if (CollUtil.isNotEmpty(invoicedReceipts)) {
                //提取serialNo不为空的数据为list<String>
                List<String> serialNoList = invoicedReceipts.stream()
                        .map(InvoicedReceipt::getSerialNo)
                        .filter(StrUtil::isNotEmpty)
                        .toList();
                if (CollUtil.isNotEmpty(serialNoList)) {
                    kingdeeInvoiceCloudLogic.billSign(String.valueOf(head.getId()), "01", String.join(",", serialNoList));
                }
            }
        }

    }

    /**
     * 红冲财务确认
     *
     * @param param
     */
    @Override
    @Transactional
    public void redReversalFinanceConfirm(RedReversalConfirmParamDTO param) {
        InvoicedApply invoicedApply = invoicedApplyService.getById(param.getId());
        invoicedApply.setRedReversalStatus(param.getApproveStatus() == 1 ? 3 : 4);
        invoicedApplyService.updateById(invoicedApply);
        //如果同意，发票要全部添加不可删除
        if (param.getApproveStatus() == 1) {
            invoicedReceiptService.update(new LambdaUpdateWrapper<InvoicedReceipt>()
                    .set(InvoicedReceipt::getNotDeleteFlag, 1)
                    .eq(InvoicedReceipt::getIaId, invoicedApply.getId()));
        }
        // 2.记录原因
        InvoicedApplyApprove approve = new InvoicedApplyApprove();
        approve.setIaId(param.getId());
        approve.setIaNo(invoicedApply.getInvoiceNo());
        approve.setApproveResult(param.getApproveStatus());
        approve.setApproveOpinion(param.getApproveOpinion());
        approve.setApproveUserId(LoginUtil.getUserId());
        approve.setApproveUserCode(LoginUtil.getAccount());
        approve.setApproveUserName(LoginUtil.getName());
        // 财务节点
        approve.setApproveNode(3);
        approve.setApproveTime(LocalDateTime.now());
        invoicedApplyApproveService.save(approve);
        List<InvoicedReceiptDTO> invoiceSelectList = param.getInvoiceSelectList();
        if (CollUtil.isNotEmpty(invoiceSelectList)){
            invoicedReceiptService.update(new LambdaUpdateWrapper<InvoicedReceipt>()
                    .set(InvoicedReceipt::getDeleteFlag, 1)
                    .in(InvoicedReceipt::getId, invoiceSelectList.stream().map(InvoicedReceiptDTO::getId).collect(Collectors.toList())));
        }
        this.deleteImg(invoicedApply.getId());
        this.toImg(invoicedApply.getId());
    }

    @Override
    @Transactional
    public void purchaseConfirmOld(InvoicedApplySaveParamDTO params) {
        if (ObjectUtil.isNull(params.getHeadData())) {
            throw new DaoException("参数异常, 请重新操作");
        }

//        if (CollectionUtils.isEmpty(params.getDetailDate())) {
//            throw new DaoException("明细数据异常, 请重新操作");
//        }
        InvoicedApplyDTO headDto = params.getHeadData();
        InvoicedApply head = invoicedApplyConvert.dto2Entity(headDto);
        // 变更的开票明细数据
//        List<InvoicedApplyItemDTO> detailList = params.getDetailDate();
        if(1 == params.getRoleType() && 1 == params.getApproveStatus()){
//            if(head.getInvoiceTotalAmount().compareTo(head.getInvoiceNetAmount())!=0){
//                throw new RuntimeException("金额不符，请重新关联发票，修改开票金额!");
//            }
//            if(head.getInvoiceTaxTotalAmount().compareTo(head.getInvoiceTaxAmount())!=0){
//                throw new RuntimeException("金额不符，请重新关联发票，修改开票金额!");
//            }

            //判断发票上传的供应商是否一致
//            List<InvoiceLeShuiDto> invoiceDetail = invoicedLesHuiService.getInvoiceDetail(head.getId());
//            Optional<InvoiceLeShuiDto> cartOptional = invoiceDetail.stream().filter(item -> !item.getSellerTaxName().equals(head.getSupplierName())).findFirst();
//            if (cartOptional.isPresent()) {
//                throw new RuntimeException("发票明细关联了其他供应商的发票,请检查!");
//            }

            //开票申请单校验预付款是否被使用
            if (CollectionUtils.isNotEmpty(params.getAddAdvances())){
                invoicedApplyPaLogic.checkAdvanceUse(params.getAddAdvances(),head.getId());
            }
        }

        // 本次变更可能存在新增的明细数据
//        List<InvoicedApplyDetail> newDetailList = Lists.newArrayList();
//        List<InvoicedApplyDetail> currDetailList = Lists.newArrayList();
//        for (InvoicedApplyItemDTO detail : detailList) {
//            if (0 == detail.getId()) {
//                newDetailList.add(detail.toIad());
//            } else {
//                currDetailList.add(detail.toIad());
//            }
//        }

        // 变更前的开票申请明细数据
        final List<InvoicedApplyDetail> oldIadList = invoicedApplyDetailService.findByInvoiceApplyId(head.getId(), Lists.newArrayList());
        // 变更前开票申请表头数据
        final InvoicedApply oldHead = invoicedApplyService.getById(head.getId());
//        if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//            oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//        }

        if (1 == params.getRoleType()) {
            // 数据状态 2:待采购确认 3:采购拒绝 6:OA审批不通过 8:财务拒绝
            if (2 != oldHead.getStatus() && 3 != oldHead.getStatus() && 6 != oldHead.getStatus() && 8 != oldHead.getStatus()) {
                throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
            }
            // 将有可能变更的数据放到原开票申请对象中
//            oldHead.setInvoiceNo(head.getInvoiceNo());
//            oldHead.setInvoiceNum(head.getInvoiceNum());
            oldHead.setInvoiceNetAmount(head.getInvoiceNetAmount());
            oldHead.setInvoiceTaxAmount(head.getInvoiceTaxAmount());
//            oldHead.setRebateAmount(head.getRebateAmount());
//            oldHead.setRntAmount(head.getRntAmount());
//            oldHead.setDeductionAmount(head.getDeductionAmount());
//            oldHead.setDntAmount(head.getDntAmount());
//            oldHead.setInvoiceTotalAmount(head.getInvoiceTotalAmount());
//            oldHead.setAllBudInnerMoney(head.getAllBudInnerMoney());
//            oldHead.setInvoiceTaxTotalAmount(head.getInvoiceTaxTotalAmount());
            oldHead.setRemark(head.getRemark());
//            oldHead.setTaxCode(head.getTaxCode());
            oldHead.setStrikePriceAmount(head.getStrikePriceAmount());
            oldHead.setActualUnpaidAmount(head.getActualUnpaidAmount());
//            if (null!=head.getStrikePriceAmount()){
//                if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//                    oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//                }
//            }
//            oldHead.setDeductionAmountTotal(head.getDeductionAmountTotal());
            oldHead.setStrikeStatus(CollectionUtils.isNotEmpty(params.getAddAdvances())?0:3);

            oldHead.setLocalCurrency(head.getLocalCurrency());
            oldHead.setOriginalCurrency(head.getOriginalCurrency());
            oldHead.setAdvanceLocalCurrency(head.getAdvanceLocalCurrency());
            oldHead.setAdvanceOriginalCurrency(head.getAdvanceOriginalCurrency());
            this.purchaseConfirm(
                    oldHead, null, params.getDelDetailIds(), params.getDelSdIds(), params.getDelSrIds(),
                    params.getAddSdIds(), params.getAddSrIds(), params.getApproveRemark(), params.getApproveStatus(), LoginUtil.getCurrentUser(),params.getManualCheckList()
            );

            //查询已经关联预付款数据，如果有就减去上次冲账金额且删除
//            List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,head.getId()));
//            if (CollectionUtils.isNotEmpty(invoicedApplyPaList)){
//                List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
//                invoicedApplyPaList.forEach(ipa->{
//                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());
//                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)){
//                        paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()));
//                        paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
//                    }
//                });
//                paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList);

//            }
            if (CollectionUtils.isNotEmpty(params.getAddAdvances())&&0 == params.getApproveStatus()){
                List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,head.getId()));
                invoicedApplyPaList.forEach(invoicedApplyPa -> {
                    //更新预付款已冲账金额
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(invoicedApplyPa.getPaId());
                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)){
                        paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()).compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:paymentAdvanceApplyDetail.getReversalMoney().subtract(invoicedApplyPa.getStrikePrice()));
                        paymentAdvanceApplyDetailService.updateById(paymentAdvanceApplyDetail);
                    }
                });
            }
            invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,head.getId()));
            if (CollectionUtils.isNotEmpty(params.getAddAdvances())&&1 == params.getApproveStatus()){
                List<InvoicedApplyPa> paList = Lists.newArrayList();
                List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
                for (InvoicedApplyPa ipa : params.getAddAdvances()) {
                    ipa.setInvoiceApplyId(head.getId());
                    ipa.setId(null);
                    ipa.setDeleteFlag(0);
//                    ipa.setPaId(paId);
                    paList.add(ipa);
//
//                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = new PaymentAdvanceApplyDetail();
//                    paymentAdvanceApplyDetail.setId(paId);
//                    //发票申请消费标识 0：未消费 1；已消费
//                    paymentAdvanceApplyDetail.setInvoicedFlag(1);
//                    paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                    //更新预付款已冲账金额
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());
                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)){
                        paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().add(ipa.getStrikePrice()));
                        paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                    }
                }

                if (!this.invoicedApplyPaService.saveBatch(paList)) {
                    throw new DaoException("保存预付款申请明细失败, 前联系管理员");
                }
                if (!this.paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList)) {
                    throw new DaoException("更新预付款申请明细失败, 前联系管理员");
                }

            }

            invoicedApplyOptLogic.addContentRecord(1, null, null, Lists.newArrayList(), null, LoginUtil.getCurrentUser());
            invoicedApplyOptLogic.addContentRecord(2, oldHead, head, oldIadList, null, LoginUtil.getCurrentUser());

        } else {
            // 数据状态 7:待财务确认
            if (7 != oldHead.getStatus()) {
                throw new DaoException("当前开票申请单的数据状态不允许修改, 请检查");
            }
//            oldHead.setStrikePriceAmount(head.getStrikePriceAmount());
//            oldHead.setActualUnpaidAmount(head.getActualUnpaidAmount());
//            if (null!=head.getStrikePriceAmount()){
//                if (BigDecimal.ZERO.compareTo(head.getStrikePriceAmount())==0){
//                    oldHead.setActualUnpaidAmount(head.getInvoiceTaxAmount());
//                }
//            }
//            oldHead.setDeductionAmountTotal(head.getDeductionAmountTotal());
            oldHead.setRemark(head.getRemark());
            //2025-07修改逻辑之前的财务确认方法
            this.financeConfirmOld(oldHead, params.getApproveRemark(), params.getApproveStatus(), LoginUtil.getCurrentUser(),params.getManualCheckList());
        }

        // 保存关联发票信息
        invoicedReceiptLogic.operateInvoice(params.getInvoicedReceiptData(),head.getId(),LoginUtil.getCurrentUser());
    }

    public void financeConfirmOld(InvoicedApply head, String approveRemark, Integer approveStatus, CurrentUserDTO user,List<AttachmentManualCheck> manualCheckList) {
        InvoicedApply updateHead = new InvoicedApply();
        updateHead.setId(head.getId());
        updateHead.setRemark(head.getRemark());
        updateHead.setUpdateTime(LocalDateTime.now());
        updateHead.setUpdateUserId(user.getUserId());
        updateHead.setUpdateUserCode(user.getLoginName());
        updateHead.setUpdateUserName(user.getName());

        // 数据状态 1:暂存发票 2:待采购确认发票 3:采购拒绝发票 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认发票 8:财务驳回发票 9:发票已确认
        if (1 == approveStatus) {
            updateHead.setFinanceConfirmTime(LocalDateTime.now());
            updateHead.setFinanceConfirmUserId(LoginUtil.getUserId());
            updateHead.setStatus(9);
            updateHead.setPostStatus(2);
            InvoicedApply old = invoicedApplyService.getById(head.getId());
            //美金对账单，到票申请交接-财务确认后，无需“财务过账”
            if (!"CNY".equals(old.getCurrencyCode())||old.getForeignCurrencyAddFlag()==1){
                updateHead.setPostStatus(6);
            }

        } else {
            updateHead.setStatus(8);
            updateHead.setPostStatus(1);

            //查询已经关联预付款数据，如果有就减去上次冲账金额且删除
            List<InvoicedApplyPa> invoicedApplyPaList = invoicedApplyPaService.list(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,head.getId()));
            if (CollectionUtils.isNotEmpty(invoicedApplyPaList)){
                List<PaymentAdvanceApplyDetail> paymentAdvanceApplyDetailList = Lists.newArrayList();
                invoicedApplyPaList.forEach(ipa->{
                    PaymentAdvanceApplyDetail paymentAdvanceApplyDetail = paymentAdvanceApplyDetailService.getById(ipa.getPaId());
                    if (ObjectUtil.isNotNull(paymentAdvanceApplyDetail)){
                        paymentAdvanceApplyDetail.setReversalMoney(paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()).compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:paymentAdvanceApplyDetail.getReversalMoney().subtract(ipa.getStrikePrice()));
                        paymentAdvanceApplyDetailList.add(paymentAdvanceApplyDetail);
                    }
                });
                paymentAdvanceApplyDetailService.updateBatchById(paymentAdvanceApplyDetailList);
                invoicedApplyPaService.remove(Wrappers.lambdaQuery(InvoicedApplyPa.class).eq(InvoicedApplyPa::getInvoiceApplyId,head.getId()));
            }
            InvoicedApply invoicedApply = invoicedApplyService.getById(head.getId());
            //1，财务驳回发票交接，增加邮件提醒，  邮件收件人：供应商（(4)财务人员、(12)业务接口人、(5)业务经理）、对账采购组窗口
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailBis.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),approveRemark);
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailFin.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),approveRemark);
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_160", emailJl.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),approveRemark);
            }
        }
        if (CollUtil.isNotEmpty(manualCheckList)){
            manualCheckList.forEach(manualCheck -> {
                if (manualCheck.getId() == null){
                    manualCheck.setCreateUser(LoginUtil.getUserId());
                    manualCheck.setCreateTime(LocalDateTime.now());
                }else {
                    manualCheck.setUpdateUser(LoginUtil.getUserId());
                    manualCheck.setUpdateTime(LocalDateTime.now());
                }
            });
            attachmentManualCheckService.saveOrUpdateBatch(manualCheckList);
        }
        if (!invoicedApplyService.updateById(updateHead)) {
            throw new DaoException("更新对账单主表数据失败, 请联系管理员");
        }


        if (!invoicedApplyApproveLogic.addApproveRecord(head.getId(), head.getInvoiceApplyNo(), approveStatus, approveRemark, 2, user)) {
            throw new DaoException("添加开票申请单审批记录失败, 请联系管理员");
        }

        // 财务通过后, 生成SRM开票申请过账数据
        if (2 == updateHead.getPostStatus()) {
            InvoicedApplyPostResult pr1 = new InvoicedApplyPostResult();
            pr1.setCreateTime(LocalDateTime.now());
            pr1.setInvoiceApplyId(head.getId());
            pr1.setInvoiceApplyNo(head.getInvoiceApplyNo());
            //查找不包含贷项的凭证 161 162
            List<InvoicedApplyDetail> details = invoicedApplyDetailLogic.findByInvoiceNo(head.getInvoiceApplyNo());
            if (CollectionUtils.isNotEmpty(details)) {
                // 凭证发票
                pr1.setPostInvoiceType(1);
            } else {
                // 贷项凭证
                pr1.setPostInvoiceType(4);
            }
            if (!invoicedApplyPostResultService.save(pr1)) {
                throw new DaoException("添加开票申请单待过账记录失败, 请联系管理员");
            }
            InvoicedApply invoicedApply = invoicedApplyService.getById(head.getId());
            //异步邮件通知 供应商 12业务接口人 4财务人员 2024-11-13 邓京术
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(invoicedApply.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailBis.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),"");
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailFin.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),"");
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailJl.getEmail(), invoicedApply.getSupplierName(), invoicedApply.getAccountStatementNo(),"");
            }
        }
    }
    /**
     * 校验开票明细中反向凭证对应的正向是否也在其中
     *
     * @param supplierCode 供应商编码
     * @param iadList      待保存的开票申请明细
     * @param orderType    入库凭证类型 1:材料类 2:运费类
     */
    private String checkInvoicedApplyDetail(String supplierCode, List<InvoicedApplyDetail> iadList, Integer orderType) {
        List<Long> rvIdList = Lists.newArrayList();
        for (InvoicedApplyDetail iad : iadList) {
            rvIdList.add(iad.getReceiveId());
        }

        final String result = receiptVoucherLogic.checkConsultVoucher(rvIdList, supplierCode, orderType);
        if (StringUtils.isNotEmpty(result)) {
            return result;
        }

        return "";
    }

    private void sendEmailToSupplier(String templeteCode, String receiver, String supplierName, String accountStatementCode, String reason) {
        try {
            final EmailTmpSingleSendDTO emailTxtSingleSendDTO = new EmailTmpSingleSendDTO();
            emailTxtSingleSendDTO.setTemplateCode(templeteCode);
            Map<String, Object> params = Maps.newHashMap();
            params.put("url", sysProp.getWebsiteUrl());
            params.put("supplierName", supplierName);
            params.put("accountCode", accountStatementCode);
            params.put("reason", reason);
            params.put("date", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            emailTxtSingleSendDTO.setParams(params);
            emailTxtSingleSendDTO.setReceiver(receiver);
            emailTxtSingleSendDTO.setSender(LoginUtil.getUserId());
            emailSendClient.async(emailTxtSingleSendDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
