package com.jwipc.finance.logic.impl;

import cn.hutool.core.collection.CollUtil;
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.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.SapResposeBody;
import com.jwipc.constant.DictCode;
import com.jwipc.constant.SignProcessType;
import com.jwipc.contract.base.ContractSendSignClientDTO;
import com.jwipc.contract.base.ContractSendSignResultClientDTO;
import com.jwipc.contract.client.ContractSignClient;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.constant.AccountContractType;
import com.jwipc.finance.constant.AccountStatementSapClient;
import com.jwipc.finance.convert.AccountSalesContractsDetailConvert;
import com.jwipc.finance.convert.AccountStatementAttachmentConvert;
import com.jwipc.finance.convert.AccountStatementConvert;
import com.jwipc.finance.dto.*;
import com.jwipc.finance.entity.*;
import com.jwipc.finance.logic.*;
import com.jwipc.finance.model.po.*;
import com.jwipc.finance.model.query.*;
import com.jwipc.finance.service.*;
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.clent.dto.SupplierDTO;
import com.jwipc.supplier.client.SupplierClient;
import com.jwipc.supplier.entity.SupplierPurchaseCategory;
import com.jwipc.supplier.service.ISupplierPurchaseCategoryService;
import com.jwipc.sys.client.*;
import com.jwipc.sys.client.dto.*;
import com.jwipc.sys.dto.BusinessAttachmentDTO;
import com.jwipc.sys.dto.KingdeeInvoiceCloudImageDTO;
import com.jwipc.sys.entity.Attachment;
import com.jwipc.sys.entity.BusinessAttachment;
import com.jwipc.sys.logic.BusinessAttachmentLogic;
import com.jwipc.sys.logic.KingdeeImageLogic;
import com.jwipc.sys.service.IAttachmentService;
import com.jwipc.sys.service.IBusinessAttachmentService;
import com.jwipc.sys.service.IPurchaseGroupService;
import com.jwipc.sys.service.IUserPurchaseGroupService;
import com.jwipc.util.MoneyToChineseUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

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

/**
 * @author shenyang.ou
 * @date 2024/3/4 11:39
 * @desc
 */
@Service
@RequiredArgsConstructor
@DS(SLAVE)
public class AccountStatementLogicImpl implements AccountStatementLogic {
    private final AccountStatementConvert accountStatementConvert;
    private final IPaymentCodApplyDetailService paymentCodApplyDetailService;
    private final IPaymentCodApplyService paymentCodApplyService;
    private final IAccountStatementService accountStatementService;
    private final IAttachmentManualCheckService attachmentManualCheckService;
    private final IAttachmentService attachmentService;
    private final AccountStatementAttachmentConvert accountStatementAttachmentConvert;
    private final AccountStatementAttachmentLogic accountStatementAttachmentLogic;
    private final DictClient dictClient;
    private final SysConfigClient sysConfigClient;
    private final TaxClient taxClient;
    private final SupplierClient supplierClient;
    private final IAccountStatementApproveService accountStatementApproveService;
    private final IAccountStatementDetailService accountStatementDetailService;
    private final IInvoicedApplyDetailService invoicedApplyDetailService;
    private final IInvoicedApplyService invoicedApplyService;
    private final AccountStatementOptLogic accountStatementOptLogic;
    private final IFinPaymentConfirmLogService finPaymentConfirmLogService;
    private final KingdeeImageLogic kingdeeImageLogic;
    private final AccountStatementApproveLogic accountStatementApproveLogic;
    private final ReceiptVoucherLogic receiptVoucherLogic;
    private final IDeductionService deductionService;
    private final SequenceClient sequenceClient;
    private final EmailSendClient emailSendClient;
    private final SysProp sysProp;
    private final AccountStatementSapClient accountStatementSapClient;
    private final BusinessAttachmentLogic businessAttachmentLogic;
    private final FileClient fileClient;
    private final IBusinessAttachmentService businessAttachmentService;
//    private final IAccountStatementAttachmentService accountStatementAttachmentService;
    private final UserClient userClient;
    private final ContractSignClient contractSignClient;
    private final ProductClient productClient;
    private final DigitalSealBusinessDetailClient digitalSealBusinessDetailClient;
    private final ISupplierPurchaseCategoryService supplierPurchaseCategoryService;
    private final IPublicHolidayInfoService publicHolidayInfoService;
    private final IPaymentStatementFilterConfigService paymentStatementFilterConfigService;
  //  private final IStatementPaymentSettingService statementPaymentSettingService;
    private final IUserPurchaseGroupService userPurchaseGroupService;
    private final IPurchaseGroupService purchaseGroupService;
    private final IAccountSalesContractsDetailService accountSalesContractsDetailService;
    private final AccountSalesContractsDetailConvert accountSalesContractsDetailConvert;
    @Override
    public PageView findByPage(AccountStatementQuery query) {
        final Page<AccountStatement> dbPage = PageUtil.toPage(query);
        query.setBusinessTypeCode(SignProcessType.ACCOUNT_STATEMENT.getBusinessNo());
        List<AccountStatementPO> accountStatementPOS = accountStatementService.findPageByQuery(dbPage, query);
        List<AccountStatementDTO> accountStatementDTOS = accountStatementConvert.po2PageListDTO(accountStatementPOS);
        accountStatementDTOS.forEach(accountStatementDTO -> {
            //增加对账单是否付款判断， 2024-12-23 邓京术
            List<PaymentCodApply> paymentCodApplyList = paymentCodApplyService.findAppDetailByAccountStatementNo(accountStatementDTO.getAccountStatementNo());
            //需要计算实际未付金额
            //对账单含税金额 应该与所有的已请款的金额累加相等，且付款完成 就计算为已付款状态为是
            BigDecimal taxAmount = accountStatementDTO.getActualUnpaidAmount() != null? accountStatementDTO.getActualUnpaidAmount() : BigDecimal.ZERO;
            BigDecimal totalPay = BigDecimal.ZERO;
            for (PaymentCodApply apply : paymentCodApplyList) {
                if (null != apply && null != apply.getStatus() && apply.getStatus() == 5) {
                    //付款申请里面的本次申请金额
                    totalPay = totalPay.add(apply.getActualityPayMoney() == null?BigDecimal.ZERO:apply.getActualityPayMoney());
                }
            }


            if (taxAmount == null ||
                    totalPay.compareTo(BigDecimal.ZERO) == 0 ||
                    totalPay.compareTo(taxAmount) != 0) {
                accountStatementDTO.setPaymentStatus("否");
            } else {
                accountStatementDTO.setPaymentStatus("是");
            }
            accountStatementDTO.setSignFileStatus(ObjectUtil.isNotNull(accountStatementDTO.getSignStatus())?1:0);
        });
        return PageUtil.getPV(accountStatementDTOS, dbPage.getTotal());
    }

    @Override
    public PageView findSalesContractByPage(AccountSalesContractsDetailQuery query) {
        final Page<AccountSalesContractsDetail> dbPage = PageUtil.toPage(query);
        List<AccountSalesContractsDetailPO> pageByQuery = accountSalesContractsDetailService.findPageByQuery(dbPage, query);
        List<AccountSalesContractsDetailDTO> accountSalesContractsDetailDTOS = accountSalesContractsDetailConvert.po2PageListDTO(pageByQuery);
        return PageUtil.getPV(accountSalesContractsDetailDTOS, dbPage.getTotal());
    }

    @Override
    public List<AccountSalesContractsDetailDTO> findSalesContractListAll(AccountSalesContractsDetailQuery query) {
        List<AccountSalesContractsDetailPO> pageByQuery = accountSalesContractsDetailService.findPageByQuery(null, query);
        List<AccountSalesContractsDetailDTO> accountSalesContractsDetailDTOS = accountSalesContractsDetailConvert.po2PageListDTO(pageByQuery);
        return accountSalesContractsDetailDTOS;
    }

    @Override
    public List<AccountStatementDTO> listAll(AccountStatementQuery query) {
        query.setBusinessTypeCode(SignProcessType.ACCOUNT_STATEMENT.getBusinessNo());
        List<AccountStatementPO> accountStatementPOS = accountStatementService.findPageByQuery(null, query);
        List<AccountStatementDTO> accountStatementDTOS = accountStatementConvert.po2PageListDTO(accountStatementPOS);
        accountStatementDTOS.forEach(accountStatementDTO -> {
            //增加对账单是否付款判断， 2024-12-23 邓京术
            List<PaymentCodApply> paymentCodApplyList = paymentCodApplyService.findAppDetailByAccountStatementNo(accountStatementDTO.getAccountStatementNo());
            //需要计算付款金额
            //对账单含税金额 应该与所有的已请款的金额累加相等，且付款完成 就计算为已付款状态为是
            BigDecimal taxAmount = accountStatementDTO.getTaxAmount();
            final BigDecimal[] totalPay = {BigDecimal.ZERO};
            paymentCodApplyList.stream().forEach(item -> {
                if (null != item && null != item.getStatus() && item.getStatus() == 5) {
                    //付款申请里面的本次申请金额
                    totalPay[0] = totalPay[0].add(item.getActualityPayMoney());
                }
            });
            if (totalPay[0].intValue() == 0 || totalPay[0].intValue() != taxAmount.intValue()) {
                accountStatementDTO.setPaymentStatus("否");
            } else {
                accountStatementDTO.setPaymentStatus("是");
            }
            accountStatementDTO.setSignFileStatus(ObjectUtil.isNotNull(accountStatementDTO.getSignStatus())?1:0);
        });
        return accountStatementDTOS;
    }

    @Override
    public AccountStatementDTO getById(Long id) {
        AccountStatement accountStatement = accountStatementService.getById(id);
        return accountStatementConvert.entity2DTO(accountStatement);
    }
    @Override
    public AccountStatementDTO getDtoById(Long id) {
        AccountStatementPO accountStatement = accountStatementService.selectPoById(id);
        AccountStatementDTO accountStatementDTO = accountStatementConvert.poy2DTO(accountStatement);
        if ("CNY".equals(accountStatementDTO.getCurrencyCode())){
            accountStatementDTO.setOriginalCurrency(accountStatementDTO.getTaxAmount().add(accountStatementDTO.getOriginalCurrency()));
        }
        return accountStatementDTO;
    }

    /**
     * 对账单保存
     *
     * @param optType      操作类型；0-新增；1-编辑；2-查看；3-主管确认；4-财务确认
     * @param headData      对账单抬头数据
     * @param statementItem 对账单明细数据
     * @param deductionIds  对账单扣款关系之扣款记录ID
     * @param rebateIds     对账单返利关系之返利记录ID
     */
    @Override
    @DS(SLAVE)
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void saveOrUpdate(Integer optType,String headData, String statementItem, String businessAttachmentItem, String deductionIds, String rebateIds) {
        if(StringUtils.isEmpty(headData)){
            throw new DaoException("参数错误, 请检查");
        }
        if(StringUtils.isEmpty(statementItem)){
            throw new DaoException("对账单明细数据错误, 请检查");
        }
        final List<StatementItemDTO> siList = JSONArray.parseArray(statementItem, StatementItemDTO.class);


        List<Long> deductionIdList = Lists.newArrayList();
        if(StringUtils.isNotEmpty(deductionIds)){
            deductionIdList.addAll(JSONArray.parseArray(deductionIds, Long.class));
        }

        List<Long> rebateIdList = Lists.newArrayList();
        if(StringUtils.isNotEmpty(rebateIds)){
            rebateIdList.addAll(JSONArray.parseArray(rebateIds, Long.class));
        }
        // 对账单主表
        AccountStatement statement = JSONObject.parseObject(headData, AccountStatement.class);
        if (statement.getId()==null){
            final String asNo = sequenceClient.getCodeSequenceNo("finance_no",6);// 最新获取方式
         //   final String asNo = sequenceClient.createfinanceSequenceNo("finance_no");
          //  final String asNo = sequenceClient.createSequenceNo("finance_no");
            statement.setAccountStatementNo(asNo);
            statement.setStatus(1);
            statement.setCreateTime(LocalDateTime.now());
            statement.setCreateUserId(LoginUtil.getUserId());
            statement.setCreateUserCode(LoginUtil.getAccount());
            statement.setCreateUserName(LoginUtil.getName());
            accountStatementService.save(statement);
        }else {
            AccountStatement accountStatement = accountStatementService.getById(statement.getId());
            statement.setAccountStatementNo(accountStatement.getAccountStatementNo());
            statement.setUpdateTime(LocalDateTime.now());
            statement.setStatus(1);
            statement.setUpdateUserId(LoginUtil.getUserId());
            statement.setUpdateUserCode(LoginUtil.getAccount());
            statement.setUpdateUserName(LoginUtil.getName());
            accountStatementDetailService.remove(Wrappers.lambdaQuery(AccountStatementDetail.class).eq(AccountStatementDetail::getAsId,statement.getId()));
            accountStatementService.saveOrUpdate(statement);
        }
        //1、创建对账单，如果收/退结束日期之前有负数的物料凭证不在本次对账范围，且还未对账，则不允许对账；
        //（161、162、122、123）（时间范围之前的也要判断）必须选择先对账掉
        ReceiveVoucherQuery query = new ReceiveVoucherQuery();
        query.setSupplierCode(statement.getSupplierCode());
        query.setCompanyCode(statement.getCompanyCode());
        query.setFactoryCode(statement.getFactoryCode());
        query.setCurrencyCode(statement.getCurrencyCode());
        query.setPostTimeEnd(DateUtil.format(statement.getInStockStartDate(), "yyyy-MM-dd"));
        query.setPoTypes(statement.getPoType());
        query.setReceiveType(statement.getOrderType());
        query.setTaxCode(statement.getTaxCode());

        query.setVoucherTypes((statement.getVoucherType()==1||statement.getVoucherType()==2)?(statement.getVoucherType()+",3"): String.valueOf(statement.getVoucherType()));
        query.setAccountStatementFlag(1);
        query.setBusinessFalg("0");
        query.setAccountUserFlag("1");

        List<StatementItemDTO> receiveVoucherDTOS = receiptVoucherLogic.provideCreateStatementList(query);
        Set<String> reNoList = new HashSet<>();
        if (CollUtil.isNotEmpty(receiveVoucherDTOS)){
            List<Long> receiveIdList = siList.stream().map(StatementItemDTO::getReceiveId).collect(Collectors.toList());
            for(StatementItemDTO dto: receiveVoucherDTOS){
                //判断dto中的receiveId不在receiveIdList中
                if (dto.getVoucherFlag().equals("H")&&StrUtil.isEmpty(dto.getAsNo())&&!receiveIdList.contains(dto.getReceiveId())){
                    reNoList.add(dto.getPoCode()+"_"+dto.getPoItemNo());
                }
            }
        }
        if (CollUtil.isNotEmpty(reNoList)){
//            throw new DaoException(StrUtil.format("收/退结束日期之前有负数的物料凭证【{}】不在本次对账范围且还未对账，不允许对账",Joiner.on(",").join(reNoList)));
            throw new DaoException(StrUtil.format("截至对账日，还存在未对账的退货订单【{}】，请先完成对账！",Joiner.on("、").join(reNoList)));
        }

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

        List<AccountStatementDetail> asdList = Lists.newArrayList();
        AtomicInteger index = new AtomicInteger(1);
        //把siList中的receiveId放list
        List<Long> receiveIdList = siList.stream().map(StatementItemDTO::getReceiveId).collect(Collectors.toList());
        //判断对账明细中是否存在已经使用过的物料凭证
        List<AccountStatementDetail> detailList = accountStatementDetailService.list(Wrappers.lambdaQuery(AccountStatementDetail.class).in(AccountStatementDetail::getReceiveId,receiveIdList).eq(AccountStatementDetail::getDeleteFlag,0));
        if (CollUtil.isNotEmpty(detailList)){
            throw new DaoException("入库凭证号："+detailList.get(0).getReceiveCode()+",已创建过对账单，无法继续创建");
        }
        for(StatementItemDTO dto: siList){
            AccountStatementDetail asd = dto.toAsd();
            //行项目
            String itemNo = StringUtils.leftPad(String.valueOf(index.get()*10), 5, "0");
            asd.setAsNo(statement.getAccountStatementNo());
            asd.setItemNo(itemNo);
            asd.setCreateUserId(LoginUtil.getUserId());
            asd.setCreateUserCode(LoginUtil.getAccount());
            asd.setCreateUserName(LoginUtil.getName());
            asd.setCreateTime(LocalDateTime.now());
            asd.setAsId(statement.getId());
            asd.setAsNo(statement.getAccountStatementNo());
            asdList.add(asd);
            index.getAndIncrement();
        }

        // 校验对账单明细的出入库明细数据
        List<Long> rvIdList = Lists.newArrayList();
        for(AccountStatementDetail asd: asdList){
            rvIdList.add(asd.getReceiveId());
        }
        final String checkResult = receiptVoucherLogic.checkConsultVoucher(rvIdList,statement.getSupplierCode(), statement.getOrderType());
        if(StringUtils.isNotEmpty(checkResult)){
            throw new DaoException(checkResult);
        }

        if(!accountStatementDetailService.saveBatch(asdList)){
            throw new DaoException("保存对账单明细数据失败, 请联系管理员");
        }

        // 将操作记录保存
        accountStatementOptLogic.addNotContentRecord(statement.getId()==null?1:2, statement.getId(), statement.getAccountStatementNo(), Lists.newArrayList(),LoginUtil.getCurrentUser());

        AccountStatementToSapDTO accountStatementToSapDTO = makeAccountStatementSapData(1,"",statement.getId()==null?JSONObject.parseObject(headData, AccountStatement.class):accountStatementService.getById(statement.getId()),null,asdList,null);
        SapResposeBody sapResposeBody = accountStatementSapClient.syncAccountStatement(accountStatementToSapDTO);
        if (StringUtils.isEmpty(sapResposeBody.getES_RET().getCODE())||sapResposeBody.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
            throw new DaoException("SAP接口报错：" + sapResposeBody.getES_RET().getMSG());
        }
    }

    //组装对账接口需要的数据
    @Override
    public AccountStatementToSapDTO makeAccountStatementSapData(Integer status,String deleteFlag,AccountStatement statementHeadData,InvoicedApply invoicedApply,List<AccountStatementDetail> asdList,String postDate){
        //组装数据传入对账数据到sap接口
        final AccountStatementToSapDTO accountStatementToSapDTO = new AccountStatementToSapDTO();
        //头
        final AccountStatementToSapDTO.ItHead itHead = new AccountStatementToSapDTO.ItHead();
        itHead.item = Lists.newArrayList();
        AccountStatementToSapDTO.Head head = new AccountStatementToSapDTO.Head();
        //对账单号
        head.setZZJSD(statementHeadData.getAccountStatementNo());
        //对账单状态 1：新建；2：已创建；3：财务复核；4：已打印 5：已结算
        head.setZSTATE(status);
        //删除标记(X:表示已删除；空：表示未删除)
        head.setZDEL(deleteFlag);
        if (null!=statementHeadData.getFinanceConfirmUserId()){
            UserDTO userDTO = userClient.getByUserId(statementHeadData.getFinanceConfirmUserId());
            head.setFNAME(ObjectUtil.isNotNull(userDTO)?userDTO.getAccountName():"");
        }else {
            //复核人名称(财务确认人员（对账）)
            head.setFNAME("");
        }
        //用户名  //改为采购组编号，因为创建人有可能是供应商， 2025-01-21 邓京术 无须取创建人代码
        head.setUNAME(statementHeadData.getPurchaseGroup());
        //上次更改日期(当前日期YYYYMMDD)
        head.setAEDAT(DateUtil.format(new Date(),"yyyyMMdd"));
        //供应商编码
        head.setLIFNR(statementHeadData.getSupplierCode());
        //公司代码
        head.setBUKRS(statementHeadData.getCompanyCode());
        //对账期间从
        head.setZDZQJC(DateUtil.format(statementHeadData.getInStockStartDate(),"yyyyMMdd"));
        //对账期间到
        head.setZDZQJD(DateUtil.format(statementHeadData.getInStockEndDate(),"yyyyMMdd"));
//        if (ObjectUtil.isNotNull(invoicedApply)){
            //含税金额合计
//            head.setZHSJE(invoicedApply.getInvoiceTaxTotalAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //未税金额合计
//            head.setZHJJE(invoicedApply.getInvoiceTotalAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //税额合计
//            head.setZHJSE(invoicedApply.getInvoiceTaxTotalAmount().subtract(invoicedApply.getInvoiceTotalAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString());
//        }else {
            //含税金额合计
            head.setZHSJE(statementHeadData.getTaxAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //未税金额合计
            head.setZHJJE(statementHeadData.getNotTaxAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //税额合计
            head.setZHJSE(statementHeadData.getTaxAmount().subtract(statementHeadData.getNotTaxAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString());
//        }
        //付款条件代码
        head.setZTERM(statementHeadData.getPaymentTermCode());
        //发票号
        head.setZFPH(ObjectUtil.isNotNull(invoicedApply)?invoicedApply.getInvoiceNo():"");
        if (ObjectUtil.isNotNull(invoicedApply)){
            //开票税额
//            final BigDecimal invoicedApplyDiff = invoicedApply.getInvoiceTaxAmount().subtract(invoicedApply.getInvoiceNetAmount());
            //税额差 用发票减系统，等于差值
//            head.setZSEC(invoicedApplyDiff.subtract(head.getZHJSE()).setScale(2, RoundingMode.HALF_UP).toPlainString());
            head.setZSEC(ObjectUtil.isNotNull(invoicedApply.getDiffTaxAmountSap())?invoicedApply.getDiffTaxAmountSap().stripTrailingZeros().toPlainString():BigDecimal.ZERO.toPlainString());
        }else {
            //税额差 用发票减系统，等于差值
            head.setZSEC("");
        }
        if (ObjectUtil.isNotNull(invoicedApply)){
            //金额差 用发票含税金额减系统，等于差值
//            head.setZJEC(invoicedApply.getInvoiceTaxAmount().subtract(statementHeadData.getTaxAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString());
            head.setZJEC(ObjectUtil.isNotNull(invoicedApply.getDiffTaxAmountSap())?invoicedApply.getDiffAmountSap().stripTrailingZeros().toPlainString():BigDecimal.ZERO.toPlainString());
        }else {
            //金额差 用发票含税金额减系统，等于差值
            head.setZJEC("");
        }
        //财务复核日期
        head.setZFHDATE(ObjectUtil.isNotNull(statementHeadData)?DateUtil.format(statementHeadData.getFinanceConfirmTime(),"yyyyMMdd"):"");
        //对账单年
        head.setZDZN(statementHeadData.getAccountStatementYear());
        //对账单月
        head.setZDZY(statementHeadData.getAccountStatementMonth());
        //货币码
        head.setWAERS(statementHeadData.getCurrencyCode());
        //对账事由
        head.setZZJSY(statementHeadData.getRemark());

        if (ObjectUtil.isNotNull(invoicedApply)&&null!=invoicedApply.getFinanceConfirmUserId()){
            UserDTO userDTO = userClient.getByUserId(invoicedApply.getFinanceConfirmUserId());
            head.setJNAME(ObjectUtil.isNotNull(userDTO)?userDTO.getAccountName():"");
//            InvoicedApplyPostResult invoicedApplyPostResult = invoicedApplyPostResultService.getOne(Wrappers.lambdaQuery(InvoicedApplyPostResult.class).eq(InvoicedApplyPostResult::getInvoiceApplyId,invoicedApply.getId()).last(" limit 1"));
            head.setZBUDAT(StringUtils.isNotEmpty(postDate)?DateUtil.format(DateUtil.parseDate(postDate),"yyyyMMdd"):"");
        }else {
            //MIRO过账日期
            head.setZBUDAT("");
            //发票校验人 财务过账按钮点击人
            head.setJNAME("");
        }
        //推送类型 只有“财务过账”按钮才是B
        head.setZTYPE(StringUtils.isNotEmpty(postDate)?"B":"A");
        itHead.item.add(head);
        //明细
        final AccountStatementToSapDTO.ItItem itItem = new AccountStatementToSapDTO.ItItem();
        itItem.item = Lists.newArrayList();
        for(AccountStatementDetail dto: asdList){
            ReceiveVoucherDTO receiveVoucherDTO = receiptVoucherLogic.getByIdAndFactoryCode(dto.getReceiveId(),statementHeadData.getFactoryCode());
            AccountStatementToSapDTO.Item item = new AccountStatementToSapDTO.Item();
            //对账单号
            item.setZZJSD(statementHeadData.getAccountStatementNo());
            //对账单行号
            item.setZEBELP(dto.getItemNo());
            //采购凭证编号
            item.setEBELN(receiveVoucherDTO.getPoCode());
            //采购凭证的项目编号
            item.setEBELP(receiveVoucherDTO.getPoItemNo());
            //物料编号
            item.setMATNR(receiveVoucherDTO.getMaterialCode());
            //采购订单计量单位
            item.setMEINS(receiveVoucherDTO.getPoMeterUnit());
            //移动类型
            item.setBWART(receiveVoucherDTO.getSapMoveType());
            //特殊库存标识
            item.setSOBKZ(receiveVoucherDTO.getSpecialInventoryFlag());
            //物料凭证编号
            item.setBELNR(receiveVoucherDTO.getMvCode());
            //物料凭证中的项目
            item.setBUZEI(receiveVoucherDTO.getMvItemNo());
            //物料凭证的年份
            item.setGJAHR(receiveVoucherDTO.getMvYear());
            //参考凭证年度
            item.setLFGJA(receiveVoucherDTO.getCvYear());
            //参考凭证的凭证号
            item.setLFBNR(receiveVoucherDTO.getCvCode());
            //参考凭证项目
            item.setLFPOS(receiveVoucherDTO.getCvItemNo());
            //税额
            item.setZSUIE(dto.getTaxAmount().subtract(dto.getNotTaxAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString());
            //其他折扣 在未税金额上扣除部分
            item.setZSPJE(ObjectUtil.isNotNull(receiveVoucherDTO.getDeductionRatio())?receiveVoucherDTO.getDeductionRatio().setScale(3, RoundingMode.HALF_UP).toPlainString():BigDecimal.ZERO.toPlainString());
            //本次结算数量
            item.setZMENGE(dto.getAsQuantity().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //含税金额
            item.setKWERT(dto.getTaxAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            //结算金额
            item.setZJSJE(dto.getNotTaxAmount().setScale(2, RoundingMode.HALF_UP).toPlainString());
            itItem.item.add(item);
        }
        accountStatementToSapDTO.setIT_HEAD(itHead);
        accountStatementToSapDTO.setIT_ITEM(itItem);
        return accountStatementToSapDTO;
    }

    @Override
    @Transactional
    public void dataDel(String ids, Integer type) {
//校验对账单明细是否被使用
        // 1.检查待删除的数据是否可以删除
        // 2.更新对账单删除标识
        // 3.更新对账单明细删除标识
        // 4.更新对账单扣款关系删除标识并更新扣款主表使用状态
        // 5.更新对账单返利关系删除标识并更新返利主表使用状态
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        List<AccountStatement> list = accountStatementService.checkAccountStatementStatus(idList);
        for(AccountStatement as: list){
//            List<AccountStatementDetail> details = accountStatementDetailService.list(Wrappers.lambdaQuery(AccountStatementDetail.class).eq(AccountStatementDetail::getAsId, as.getId()).eq(AccountStatementDetail::getDeleteFlag, 0));
//            if (CollectionUtils.isNotEmpty(details)){
//                for (AccountStatementDetail detail : details){
//                    InvoicedApplyDetail invoicedApplyDetail = invoicedApplyDetailService.getOne(Wrappers.lambdaQuery(InvoicedApplyDetail.class).eq(InvoicedApplyDetail::getAsdId, detail.getId()).eq(InvoicedApplyDetail::getDeleteFlag, 0).last(" limit 1"));
//                    if (ObjectUtil.isNotNull(invoicedApplyDetail)){
//                        throw new DaoException("对账单: " + as.getAccountStatementNo() + ", 行号："+detail.getItemNo()+"不能被删除，已被开票申请："+invoicedApplyDetail.getIaNo()+"，行号："+invoicedApplyDetail.getItemNo()+"使用");
//                    }
//                }
//            }

            InvoicedApply invoicedApply = invoicedApplyService.getOne(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getAccountStatementId,as.getId()).eq(InvoicedApply::getDeleteFlag,0).last(" limit 1"));
            if (ObjectUtil.isNotNull(invoicedApply)){
                throw new DaoException("对账单: " + as.getAccountStatementNo() + "不能被删除，已被开票申请："+invoicedApply.getInvoiceApplyNo()+"使用");
            }
            if (type!=null&&type==1){
                as.setUpdateTime(LocalDateTime.now());
                as.setUpdateUserId(LoginUtil.getUserId());
                as.setUpdateUserCode(LoginUtil.getAccount());
                as.setUpdateUserName(LoginUtil.getName());
                as.setDeleteFlag(1);
            }else {
                if(1 == as.getStatus() || 3 == as.getStatus() || 9 == as.getStatus() || 8 == as.getStatus()){
                    as.setUpdateTime(LocalDateTime.now());
                    as.setUpdateUserId(LoginUtil.getUserId());
                    as.setUpdateUserCode(LoginUtil.getAccount());
                    as.setUpdateUserName(LoginUtil.getName());
                    as.setDeleteFlag(1);
                }else {
                    throw new DaoException("对账单: " + as.getAccountStatementNo() + ", 当前状态不能被删除");
                }
            }
        }

        if(CollectionUtils.isNotEmpty(list)){
            if(!accountStatementService.updateBatchById(list)){
                throw new DaoException("对账单删除失败, 请联系管理员");
            }
        }

        if(!accountStatementDetailService.deleteByAsIdList(idList)){
            throw new DaoException("对账单明细删除失败, 请联系管理员");
        }

        accountStatementAttachmentLogic.deleteByAsIdList(idList);

        for (Long id : idList){
            AccountStatement accountStatement = accountStatementService.getById(id);
            List<AccountStatementDetail> asdList = accountStatementDetailService.list(Wrappers.lambdaQuery(AccountStatementDetail.class).eq(AccountStatementDetail::getAsId,id));
            AccountStatementToSapDTO accountStatementToSapDTO = makeAccountStatementSapData(1,"X",accountStatement,null,asdList,null);
            SapResposeBody sapResposeBody = accountStatementSapClient.syncAccountStatement(accountStatementToSapDTO);
            if (StringUtils.isEmpty(sapResposeBody.getES_RET().getCODE())||sapResposeBody.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
                throw new DaoException("SAP接口报错：" + sapResposeBody.getES_RET().getMSG());
            }
        }
    }

    /**
     * 提交对账单进行确认
     *
     * @param ids 对账单ID集合
     */
    @Override
    @Transactional
    public void submitConfirm(String ids) {
        final List<Long> idList = JSONArray.parseArray(ids, Long.class);
        List<AccountStatement> list = accountStatementService.checkAccountStatementStatus(idList);
        for(AccountStatement as: list){
            if(1 == as.getStatus() || 3 == as.getStatus()){
                as.setUpdateTime(LocalDateTime.now());
                as.setUpdateUserId(LoginUtil.getUserId());
                as.setUpdateUserCode(LoginUtil.getAccount());
                as.setUpdateUserName(LoginUtil.getName());
                as.setStatus(2);
            }else {
                throw new DaoException("对账单: " + as.getAccountStatementNo() + ", 当前状态不能被提交");
            }
        }

        if(CollectionUtils.isNotEmpty(list)){
            if(!accountStatementService.updateBatchById(list)){
                throw new DaoException("对账单状态更新失败, 请联系管理员");
            }
        }
        for (Long id : idList){
            AccountStatement accountStatement = accountStatementService.getById(id);
            List<AccountStatementDetail> asdList = accountStatementDetailService.list(Wrappers.lambdaQuery(AccountStatementDetail.class).eq(AccountStatementDetail::getAsId,id));
            AccountStatementToSapDTO accountStatementToSapDTO = makeAccountStatementSapData(2,"",accountStatement,null,asdList,null);
            SapResposeBody sapResposeBody = accountStatementSapClient.syncAccountStatement(accountStatementToSapDTO);
            if (StringUtils.isEmpty(sapResposeBody.getES_RET().getCODE())||sapResposeBody.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
                throw new DaoException("SAP接口报错：" + sapResposeBody.getES_RET().getMSG());
            }
        }
    }

    @Override
    @Transactional
    public void approveOperation(AccountStatementApproveDTO params) {
        AccountStatementDTO head = params.getHeadData();

        final AccountStatement oldHead = accountStatementService.getById(head.getId());
        // 后续存审批记录需要对账单号
        head.setAccountStatementNo(oldHead.getAccountStatementNo());
        head.setPushOaNum(oldHead.getPushOaNum());

        // 获取数据库中存储的对账单明细
        AccountStatementDetailQuery query = new AccountStatementDetailQuery();
        query.setAsId(head.getId());
        final List<AccountStatementDetail> oriData = accountStatementDetailService.selectDataByQuery(null, query);

        // 确认后的对账明细数据
        List<StatementItemDTO> siList = params.getStatementItem();
        // 确认是删除的对账单明细ID
        List<Long> dsiIdList = params.getDelSiIds();

        // 最终结果
        String message = "";

        // 采购审批确认对账单
        if(1 == params.getRoleType()){
            // 以下数据ID只有采购确认对账单时才可能有值
            List<Long> deductionIdList = params.getAddDeductionIds();
            List<Long> ddIdList = params.getDelDeductionIds();
            List<Long> rebateIdList = params.getAddRebateIds();
            List<Long> drIdList = params.getDelRebateIds();

            // 数据状态 1:暂存 2:待采购确认 3:采购拒绝 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认 8:财务拒绝 9:确认通过
            if(2 == oldHead.getStatus() || 6 == oldHead.getStatus() || 8 == oldHead.getStatus()){
                // 设置确认日志
                if (CollectionUtils.isNotEmpty(params.getLogDetailList())) {
                    setConfirmLog(params.getLogDetailList(), oldHead.getId(), oldHead.getAccountStatementNo());
                }
                message = this.purchaseApprove(params.getApproveStatus(), params.getApproveOpinion(), head, siList, dsiIdList, deductionIdList, ddIdList, rebateIdList, drIdList, LoginUtil.getCurrentUser(),params.getManualCheckList());
            }else {
                throw new DaoException("对账单不能进行采购确认操作, 请检查对账单状态");
            }
        }

        // 财务审批确认对账单
        if(2 == params.getRoleType()){
            // 数据状态 7:待财务确认
//            if(7 != oldHead.getStatus()){
//                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(this.returnMessage("对账单不能进行采购确认操作, 请检查对账单状态"));
//            }
            this.financeApprove(params.getApproveStatus(), params.getApproveOpinion(), head, LoginUtil.getCurrentUser(),params.getManualCheckList());
        }

        // 将操作记录保存
        if(CollectionUtils.isNotEmpty(dsiIdList)){
            accountStatementOptLogic.addNotContentRecord(3, head.getId(), head.getAccountStatementNo(), dsiIdList, LoginUtil.getCurrentUser());
        }

        if(CollectionUtils.isNotEmpty(siList)){
            List<Long> addAsdIdList = Lists.newArrayList();
            List<AccountStatementDetail> editAsdIdList = Lists.newArrayList();
            for(StatementItemDTO dto: siList){
                if(null == dto.getId() || 0L == dto.getId()){
                    addAsdIdList.add(dto.getId());
                }else {
                    editAsdIdList.add(dto.toAsd());
                }
            }
            accountStatementOptLogic.addNotContentRecord(1, head.getId(), head.getAccountStatementNo(), addAsdIdList, LoginUtil.getCurrentUser());
            accountStatementOptLogic.addOptContentRecord(head.getId(), head.getAccountStatementNo(), oriData, editAsdIdList, LoginUtil.getCurrentUser());
        }
    }

    /**
     * 设置确认日志
     * @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(propagation = Propagation.REQUIRED)
    public List<String> approveCheck(AccountStatementApproveDTO params) {
        List<String> resultList = new ArrayList<>();
        AccountStatement accountStatement = accountStatementService.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 asId         对账单ID
     * @param revokeReason 撤销原因
     * @return 结果
     */
    @Override
    public void revokeFinConfirm(Long asId, String revokeReason) {
        final AccountStatement statement = accountStatementService.getById(asId);
        if(null == statement){
            throw new DaoException("系统未找到相应的对账单信息");
        }
        if(7 != statement.getStatus()){
            throw new DaoException("对账单不能进行撤销操作, 请检查对账单状态");
        }

        // 1.撤销时对账单状态由7(待财务确认)变更为2(待采购确认)
        AccountStatement updateHead = new AccountStatement();
        updateHead.setId(statement.getId());
        updateHead.setStatus(2);
        updateHead.setUpdateUserId(LoginUtil.getUserId());
        updateHead.setUpdateUserCode(LoginUtil.getAccount());
        updateHead.setUpdateUserName(LoginUtil.getName());
        updateHead.setUpdateTime(LocalDateTime.now());
        accountStatementService.updateById(updateHead);

        // 2.记录撤销原因
        AccountStatementApprove approve = new AccountStatementApprove();
        approve.setAsId(statement.getId());
        approve.setAsNo(statement.getAccountStatementNo());
        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());
        accountStatementApproveService.save(approve);
    }

    /**
     * 财务撤销财务已确认状态的对账单
     *
     * @param asId         对账单ID
     * @param revokeReason 撤销原因
     * @return 结果
     */
    @Override
    public void revokeFinConfirmed(Long asId, String revokeReason) {
        final AccountStatement statement = accountStatementService.getById(asId);
        if(null == statement){
            throw new DaoException("系统未找到相应的对账单信息");
        }
        if(9 != statement.getStatus()){
            throw new DaoException("对账单不能进行撤销操作, 请检查对账单状态");
        }

        InvoicedApply invoicedApply = invoicedApplyService.getOne(Wrappers.lambdaQuery(InvoicedApply.class).eq(InvoicedApply::getAccountStatementId,statement.getId()).eq(InvoicedApply::getDeleteFlag,0).last(" limit 1"));
        if (ObjectUtil.isNotNull(invoicedApply)){
            throw new DaoException("对账单: " + statement.getAccountStatementNo() + "不能被撤销，已被开票申请："+invoicedApply.getInvoiceApplyNo()+"使用");
        }

        // 1.撤销时对账单状态由7(待财务确认)变更为2(待采购确认)
        AccountStatement updateHead = new AccountStatement();
        updateHead.setId(statement.getId());
        updateHead.setStatus(7);
        updateHead.setUpdateUserId(LoginUtil.getUserId());
        updateHead.setUpdateUserCode(LoginUtil.getAccount());
        updateHead.setUpdateUserName(LoginUtil.getName());
        updateHead.setUpdateTime(LocalDateTime.now());
        accountStatementService.updateById(updateHead);

        // 2.记录撤销原因
        AccountStatementApprove approve = new AccountStatementApprove();
        approve.setAsId(statement.getId());
        approve.setAsNo(statement.getAccountStatementNo());
        approve.setApproveResult(3);
        approve.setApproveOpinion(revokeReason);
        approve.setApproveUserId(LoginUtil.getUserId());
        approve.setApproveUserCode(LoginUtil.getAccount());
        approve.setApproveUserName(LoginUtil.getName());
        // 撤销只能由采购操作
        approve.setApproveNode(2);
        approve.setApproveTime(LocalDateTime.now());
        accountStatementApproveService.save(approve);
        //
        //异步邮件通知 供应商 12业务接口人 4财务人员 2024-11-14 邓京术
        SupplierContactsDTO emailBis = supplierClient.getDefaultContact(statement.getSupplierCode(), "12");
        SupplierContactsDTO emailFin = supplierClient.getDefaultContact(statement.getSupplierCode(), "4");
        if (ObjectUtil.isNotNull(emailBis)){
            sendEmailToSupplier("JW_POST_114", emailBis.getEmail(), statement.getSupplierName(), statement.getAccountStatementNo(),"");
        }
        if (ObjectUtil.isNotNull(emailFin)){
            sendEmailToSupplier("JW_POST_114", emailFin.getEmail(), statement.getSupplierName(), statement.getAccountStatementNo(),"");
        }
    }

    /**
     * 更新对账单明细已开票标识以及对账单的已完成开票标识
     *
     * @param asdIdList           对账单明细ID集合
     * @param invoiceCompleteFlag 开票完成标识 0:未完成 1:已完成
     */
    @Override
    public void updateInvoiceCompleteFlag(List<Long> asdIdList, int invoiceCompleteFlag) {
        List<AccountStatementDetail> asdList = Lists.newArrayList();
        for(Long asdId: asdIdList){
            AccountStatementDetail asd = new AccountStatementDetail();
            asd.setId(asdId);
            asd.setInvoiceCompleteFlag(invoiceCompleteFlag);
            asdList.add(asd);
        }
        // 更新对账单明细中的开票标识
        if(CollectionUtils.isNotEmpty(asdList)){
            accountStatementDetailService.updateBatchById(asdList);
        }

        // 根据对账单明细获取对账单ID集合
        AccountStatementDetailQuery query = new AccountStatementDetailQuery();
        query.setAsdIdList(asdIdList);
        final List<AccountStatementDetail> detailList = accountStatementDetailService.selectDataByQuery(null, query);
        List<Long> asIdList = Lists.newArrayList();
        for(AccountStatementDetail detail: detailList){
            Long asId = detail.getAsId();
            if(!asIdList.contains(asId)){
                asIdList.add(asId);
            }
        }

        List<AccountStatement> asList = Lists.newArrayList();
        // 开票未完成
        if(invoiceCompleteFlag == 0){
            for(Long asId: asIdList){
                AccountStatement as = new AccountStatement();
                as.setInvoiceCompleteFlag(invoiceCompleteFlag);
                as.setId(asId);
                asList.add(as);
            }

            // 更新对账单开票标识
            if(CollectionUtils.isNotEmpty(asList)){
                accountStatementService.updateBatchById(asList);
            }
        }
        // 开票完成
        this.updateInvoiceCompleteFlagAuto(asIdList,asList);
    }

    /**
     * 更新对账单已开票标识
     *
     * @param asId 对账单ID
     */
    @Override
    public void updateInvoiceCompleteFlagByAsId(Long asId, int invoiceCompleteFlag) {
        AccountStatement as = new AccountStatement();
        as.setInvoiceCompleteFlag(invoiceCompleteFlag);
        as.setId(asId);
        accountStatementService.updateById(as);
    }

    @Override
    public CopeWithUnclearDTO getCopeWithUnclear(String companyCode, String supplierCode, String currency, String inStockEndDate) {
        final CopeWithUnclearSapDTO.Item1 item1 = new CopeWithUnclearSapDTO.Item1();
        item1.item = Lists.newArrayList();
        final CopeWithUnclearSapDTO.Item item = new CopeWithUnclearSapDTO.Item();
        item.BUKRS = companyCode;
        item.LIFNR = supplierCode;
        item.WAERS = currency;
        item.BUDAT = StringUtils.replace(inStockEndDate, "-", "");
        item1.item.add(item);
        CopeWithUnclearSapDTO componentCountSapDTO = new CopeWithUnclearSapDTO();
        componentCountSapDTO.setIT_HEAD(item1);
        CopeWithUnclearResponseDTO copeWithUnclearResponseDTO = accountStatementSapClient.getCopeWithUnclear(componentCountSapDTO);
        if (copeWithUnclearResponseDTO.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
            throw new DaoException("SAP接口报错：" + copeWithUnclearResponseDTO.getES_RET().getMSG());
        }
        final CopeWithUnclearResponseDTO.Item1 itItem = copeWithUnclearResponseDTO.getIT_DATA();
        final List<CopeWithUnclearResponseDTO.Item2> itemList = Objects.nonNull(itItem) ? itItem.item : Lists.newArrayList();
        CopeWithUnclearDTO copeWithUnclearDTO = new CopeWithUnclearDTO();
        if (CollectionUtils.isNotEmpty(itemList)){
            copeWithUnclearDTO.setBUKRS(itemList.get(0).BUKRS);
            copeWithUnclearDTO.setLIFNR(itemList.get(0).LIFNR);
            copeWithUnclearDTO.setHKONT(itemList.get(0).HKONT);
            copeWithUnclearDTO.setTXT20(itemList.get(0).TXT20);
            copeWithUnclearDTO.setWAERS(itemList.get(0).WAERS);
            copeWithUnclearDTO.setAP_DMBTR(itemList.get(0).AP_DMBTR);
            copeWithUnclearDTO.setAP_WRBTR(itemList.get(0).AP_WRBTR);
        }
        return copeWithUnclearDTO;
    }

    @Override
    public CopeWithUnclearDTO payablePayment(String companyCode, String supplierCode,String currencyCode) {
        final AccountAmountToSapDTO.Item1 item1 = new AccountAmountToSapDTO.Item1();
        item1.item = Lists.newArrayList();
        final AccountAmountToSapDTO.Item item = new AccountAmountToSapDTO.Item();
        item.BUKRS = companyCode;
        item.LIFNR = supplierCode;
        item1.item.add(item);
        AccountAmountToSapDTO componentCountSapDTO = new AccountAmountToSapDTO();
        componentCountSapDTO.setIS_DATA(item1);
        AccountAmountResposeDTO accountAmountResposeDTO = accountStatementSapClient.getSapAmount(componentCountSapDTO);
        if (accountAmountResposeDTO.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
            throw new DaoException("SAP接口报错：" + accountAmountResposeDTO.getES_RET().getMSG());
        }
        final AccountAmountResposeDTO.Item1 itItem = accountAmountResposeDTO.getET_DATA();
        final List<AccountAmountResposeDTO.Item> itemList = Objects.nonNull(itItem) ? itItem.item : Lists.newArrayList();
        CopeWithUnclearDTO copeWithUnclearDTO = new CopeWithUnclearDTO();
        if (CollectionUtils.isNotEmpty(itemList)){
            boolean exists = false;
            for (AccountAmountResposeDTO.Item detail: itemList){
                if (detail.WAERS.equals(currencyCode)){
                    copeWithUnclearDTO.setBUKRS(detail.BUKRS);
                    copeWithUnclearDTO.setLIFNR(detail.LIFNR);
                    copeWithUnclearDTO.setWAERS(detail.WAERS);
                    copeWithUnclearDTO.setDMBTR01(detail.DMBTR01);
                    copeWithUnclearDTO.setDMBTR02(detail.DMBTR02);
                    copeWithUnclearDTO.setZOVBTR(detail.ZOVBTR);
                    copeWithUnclearDTO.setZNOBTR0(detail.ZNOBTR0);
                    exists = true;
                }
            }
            if (!exists) {
                throw new DaoException("未找到币种"+currencyCode+"的数据");
            }

        }
        return copeWithUnclearDTO;
    }

    /**
     * 查询对账单或开票申请列表
     *
     * @param query 查询条件
     * @return 结果
     */
    @Override
    public List<AccountStatementDTO> accountOrApplyList(AccountStatementQuery query) {
        List<PaymentStatementFilterConfig> statementFilterlist = paymentStatementFilterConfigService.list(Wrappers.lambdaQuery(PaymentStatementFilterConfig.class).eq(PaymentStatementFilterConfig::getDeleteFlag,0));
        List<AccountStatementPO> accountStatementPOS = accountStatementService.accountOrApplyList(null, query);
        List<AccountStatementDTO> accountStatementDTOS = accountStatementConvert.po2PageListDTO(accountStatementPOS);
       for(AccountStatementDTO accountStatementDTO:accountStatementDTOS){
           accountStatementDTO.setAlreadyApplyAmount(BigDecimal.ZERO);
           accountStatementDTO.setAlreadyPaymentAmount(BigDecimal.ZERO);
           accountStatementDTO.setStrikePriceAmount(accountStatementDTO.getStrikePriceAmount()==null?BigDecimal.ZERO:accountStatementDTO.getStrikePriceAmount());
           accountStatementDTO.setActualUnpaidAmount(accountStatementDTO.getActualUnpaidAmount()==null?accountStatementDTO.getTaxAmount():accountStatementDTO.getActualUnpaidAmount());
           //材料购销合同状态
           String paymentWay = query.getPaymentWay();
           Integer contractSupplementStatus = accountStatementDTO.getContractSupplementStatus();
           if(paymentWay.contains("C")){
               //承兑汇票
               if(accountStatementDTO.getItemSalesAgreementSignStatus()!=null){
                   if(contractSupplementStatus!=null){
                       //合同补录状态；0-无；1-待复核；2-复核未通过；3-复核通过
                       if( contractSupplementStatus==3){
                           accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.OK_UPLOAD.getValue());
                       }else   if( contractSupplementStatus==2){
                           accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.NG_PASS.getValue());
                       }else   if( contractSupplementStatus==1){
                           accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.NG_CHECK.getValue());
                       }else{
                           accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.OK_UPLOAD.getValue());
                       }
                   }else{
                       accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.OK_UPLOAD.getValue());
                   }
               }else{
                   accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.NG_UPLOAD.getValue());
               }
           }else{
               accountStatementDTO.setItemSalesAgreementSignStatus(AccountContractType.NO_UPLOAD.getValue());
           }
           //加工费购销合同状态
           String supplierCode = accountStatementDTO.getSupplierCode();
           if("9999".equals(supplierCode)){
               accountStatementDTO.setSalesProcessAgreementSignStatus(accountStatementDTO.getSalesProcessAgreementSignStatus()!=null?AccountContractType.OK_UPLOAD.getValue():AccountContractType.NG_UPLOAD.getValue());
           }else{
               accountStatementDTO.setSalesProcessAgreementSignStatus(AccountContractType.NO_UPLOAD.getValue());
           }
        }
//        accountStatementDTOS.forEach(accountStatementDTO -> {
//
//        });
        List<AccountStatementDTO> paymentAdvanceApplyList= Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accountStatementDTOS)){
            //根据已获取的过账数据筛选已经货到付款的数据
            List<CreatePcaDetailPO> alreadyData = paymentCodApplyDetailService.findByAccountCodeAndItem(accountStatementPOS);
            //处理数据开票数据
            for(AccountStatementDTO detailDto:accountStatementDTOS){
                for(CreatePcaDetailPO dto:alreadyData){
                    if(detailDto.getAccountStatementNo().equals(dto.getDataKey())){
                        //已申请金额
                        detailDto.setAlreadyApplyAmount(detailDto.getAlreadyApplyAmount().add(dto.getBudInnerMoney()).add(dto.getBudOutMoney()));
                        //已付款金额
                        if(dto.getStatus() == 5){
                            detailDto.setAlreadyPaymentAmount(detailDto.getAlreadyPaymentAmount().add(dto.getBudInnerMoney()).add(dto.getBudOutMoney()));
                        }
                        break;
                    }
                }
                detailDto.setApplyAmount(detailDto.getActualUnpaidAmount().subtract(detailDto.getAlreadyApplyAmount() == null? BigDecimal.ZERO:detailDto.getAlreadyApplyAmount()));
                //如果可申请付款金额不为0，可以继续付款
                if (detailDto.getApplyAmount().compareTo(BigDecimal.ZERO)!=0){
                    paymentAdvanceApplyList.add(detailDto);
                }
            }
        }

        //2025-02-04新增对账单付款查询过滤逻辑
        if(CollectionUtils.isNotEmpty(statementFilterlist) && CollectionUtils.isNotEmpty(paymentAdvanceApplyList)) {
            //存在过滤的对账单则删除不返回
            Set<String> StatementNoSet = statementFilterlist.stream()
                    .map(PaymentStatementFilterConfig::getAccountStatementNo)
                    .collect(Collectors.toSet());
            Iterator<AccountStatementDTO> iterator = paymentAdvanceApplyList.iterator();
            while (iterator.hasNext()) {
                AccountStatementDTO entity = iterator.next();
                if (StatementNoSet.contains(entity.getAccountStatementNo())) {
                    iterator.remove();
                }
            }
        }
        return paymentAdvanceApplyList;
    }

    /**
     * 上传签章文件
     * @param signFile 文件
     * @param signFile 文件id
     * @param id 对账单id
     */
    @Override
    public void saveSignFile(Long signFile, Long id) {
        DigitalSealBusinessDetailParamClientDTO paramClientDTO = DigitalSealBusinessDetailParamClientDTO.builder()
                .businessId(id)
                .businessTypeCode(SignProcessType.ACCOUNT_STATEMENT.getBusinessNo())
                .fileId(signFile)
                .signStatus(2)
                .createTime(LocalDateTime.now())
                .build();
        digitalSealBusinessDetailClient.save(paramClientDTO);
//        String fileKey = contractSignClient.uploadSignFile(file, String.valueOf(signFile));
//        accountStatementService.update(new LambdaUpdateWrapper<AccountStatement>().set(AccountStatement::getSignFile,signFile)
//                .set(AccountStatement::getSignFileStatus, SignFileStatus.SIGN_UPLOAD.getStatus())
//                .set(AccountStatement::getFileKey,fileKey)
//                .eq(AccountStatement::getId,id));
    }
    @Override
    public void saveSignFile1(String signFile, Long id,String businessTypeCode) {
        //signFile为逗号隔开转list
        List<String> signFileList = Arrays.asList(signFile.split(","));
        for (String signFile1 : signFileList){
            DigitalSealBusinessDetailParamClientDTO paramClientDTO = DigitalSealBusinessDetailParamClientDTO.builder()
                    .businessId(id)
                    .businessTypeCode(businessTypeCode)
                    .fileId(Long.valueOf(signFile1))
                    .signStatus(2)
                    .createTime(LocalDateTime.now())
                    .build();
            digitalSealBusinessDetailClient.save(paramClientDTO);
        }


        InvoicedApply invoicedApply = invoicedApplyService.getOne(new LambdaQueryWrapper<InvoicedApply>().eq(InvoicedApply::getAccountStatementId, id).eq(InvoicedApply::getDeleteFlag, 0));
        if (ObjectUtil.isNotNull(invoicedApply)){
            if (invoicedApply.getStatus()==9&&invoicedApply.getPostStatus()==5){
                invoicedApply.setContractSupplementStatus(1);
                invoicedApplyService.updateById(invoicedApply);
            }
        }
//        String fileKey = contractSignClient.uploadSignFile(file, String.valueOf(signFile));
//        accountStatementService.update(new LambdaUpdateWrapper<AccountStatement>().set(AccountStatement::getSignFile,signFile)
//                .set(AccountStatement::getSignFileStatus, SignFileStatus.SIGN_UPLOAD.getStatus())
//                .set(AccountStatement::getFileKey,fileKey)
//                .eq(AccountStatement::getId,id));
    }

    /**
     * 一步发起签署
     *
     * @param id 对账单id
     */
    @Override
    public void sendSign(String id) {
        AccountStatement accountStatement = accountStatementService.getById(id);
        ContractSendSignClientDTO contractSendSignClientDTO = ContractSendSignClientDTO.builder()
                .title(StrUtil.format("对账单：{}发起签署",accountStatement.getAccountStatementNo()))
                .companyCode(accountStatement.getCompanyCode())
                .supplierCode(accountStatement.getSupplierCode())
                .fileKey(accountStatement.getFileKey())
                .contractSignOrder("2")
                .build();
        ContractSendSignResultClientDTO resultClientDTO = contractSignClient.sendSignClient(contractSendSignClientDTO, SignProcessType.ACCOUNT_STATEMENT);
        accountStatementService.update(new LambdaUpdateWrapper<AccountStatement>().set(AccountStatement::getSignFlowId,resultClientDTO.getSignFlowId())
                .set(AccountStatement::getSignStatus, resultClientDTO.getSignFlowStatus())
                .eq(AccountStatement::getId,id));
    }

    @Override
    public Map<String, Object> printStatement(Long id) {
        Map<String, Object> map = new HashMap<>();
        AccountStatementDTO  accountStatementDTO = this.getDtoById(id);
        //字典赋值
        DictDTO dictDTO = dictClient.getDictByTypeAndCode(DictCode.PAYMENT_TERMS.getCode(), accountStatementDTO.getPaymentTermCode());
        if (ObjectUtil.isNotNull(dictDTO)){
            accountStatementDTO.setPaymentTermName(dictDTO.getName());
        }
        map.put("agencyFeeRate",sysConfigClient.getTextConfig("agencyFeeRate"));
        //查询供应商品类表中的承兑期限放到购销合同模板上

        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        accountStatementDTO.setCreateTimeStr(accountStatementDTO.getCreateTime().format(formatter1));
        if (Objects.nonNull(accountStatementDTO.getFinanceConfirmTime())){
            accountStatementDTO.setFinanceConfirmTimeStr(accountStatementDTO.getFinanceConfirmTime().format(formatter1));
        }
        if (Objects.nonNull(accountStatementDTO) &&
                Objects.nonNull(accountStatementDTO.getAccountStatementYear())
                && Objects.nonNull(accountStatementDTO.getAccountStatementMonth())){
            YearMonth yearMonth = YearMonth.of(Integer.parseInt(accountStatementDTO.getAccountStatementYear()),
                    Integer.parseInt(accountStatementDTO.getAccountStatementMonth()));
            LocalDate firstDayOfMonth = yearMonth.atDay(1);
            LocalDate lastDayOfMonth = yearMonth.atEndOfMonth();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");
//            accountStatementDTO.setAccountStatementPeriod(formatter.format(firstDayOfMonth)+"到"+formatter.format(lastDayOfMonth));
            accountStatementDTO.setAccountStatementPeriod(DateUtil.format(accountStatementDTO.getInStockStartDate(),"yyyy.MM.dd")+"到"+DateUtil.format(accountStatementDTO.getInStockEndDate(),"yyyy.MM.dd"));
        }
        map.put("accountStatement",accountStatementDTO);
//        model.addAttribute("accountStatement", accountStatementDTO);
        //人民币含税，非人民币不含税
        if ("CNY".equalsIgnoreCase(accountStatementDTO.getCurrencyCode())) {
            accountStatementDTO.setIncludeTax("含税");
        } else {
            accountStatementDTO.setIncludeTax("不含税");
            accountStatementDTO.setToBeInvoiced("(待开票)");
        }
        SupplierContactsDTO defaultContact = supplierClient.getDefaultContact(accountStatementDTO.getSupplierCode(), "4");
        SupplierDTO supplierDTO = supplierClient.getSupplierByCode(accountStatementDTO.getSupplierCode());
//        model.addAttribute("supplierInvoiced", defaultContact);
        map.put("supplier",supplierDTO);
        map.put("supplierInvoiced",defaultContact);

//        model.addAttribute("data", accountStatementDTO);
        map.put("data",accountStatementDTO);

        //明细数据
        List<StatementItemPO> statementItemDTOS = accountStatementDetailService.findByStatementIdAndFactoryCode(id,accountStatementDTO.getFactoryCode());

        Map<String,String> materiaNameMap = new HashMap<>();
        for (StatementItemPO po : statementItemDTOS) {
            po.setTaxPriceStr(String.valueOf(po.getTaxPrice().setScale(5,RoundingMode.HALF_UP)));
            //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称，打印的时候取短描述， 2024-08-14 邓京术
            initMaterialName(po, materiaNameMap);
        }


//        model.addAttribute("detailList",statementItemDTOS);
        map.put("detailList",statementItemDTOS);

        // 金额合计
        JSONObject jeHj = new JSONObject();
//        AtomicReference<BigDecimal> sumNotTaxAmount = new AtomicReference<>(BigDecimal.ZERO);
//        statementItemDTOS.forEach(item -> {
//            BigDecimal amount = Optional.ofNullable(item.getNotTaxAmount())
//                    .orElse(BigDecimal.ZERO);
//            BigDecimal currentSum = sumNotTaxAmount.get();
//            BigDecimal newSum = currentSum.add(amount).setScale(2, RoundingMode.HALF_UP);
//            sumNotTaxAmount.set(newSum);
//        });
//        BigDecimal sqje = statementItemDTOS.stream().map(StatementItemPO::getNotTaxAmount).filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jeHj.put("sqje", statementItemDTOS.stream().map(StatementItemPO::getNotTaxAmount).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
//        AtomicReference<BigDecimal> sumTaxAmount = new AtomicReference<>(BigDecimal.ZERO);
//        statementItemDTOS.forEach(item -> {
//            BigDecimal amount = Optional.ofNullable(item.getTaxAmount())
//                    .orElse(BigDecimal.ZERO);
//            BigDecimal currentSum = sumTaxAmount.get();
//            BigDecimal newSum = currentSum.add(amount).setScale(2, RoundingMode.HALF_UP);
//            sumTaxAmount.set(newSum);
//        });


//        BigDecimal hsje = statementItemDTOS.stream().map(StatementItemPO::getTaxAmount).filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jeHj.put("hsje",statementItemDTOS.stream().map(StatementItemPO::getTaxAmount).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
//        AtomicReference<BigDecimal> sumDiffTaxAmount = new AtomicReference<>(BigDecimal.ZERO);
//        statementItemDTOS.forEach(item -> {
//            BigDecimal amount = Optional.ofNullable(item.getDiffTaxAmount())
//                    .orElse(BigDecimal.ZERO);
//            BigDecimal currentSum = sumDiffTaxAmount.get();
//            BigDecimal newSum = currentSum.add(amount).setScale(2, RoundingMode.HALF_UP);
//            sumDiffTaxAmount.set(newSum);
//        });

//        BigDecimal hsce = statementItemDTOS.stream().map(StatementItemPO::getDiffTaxAmount).filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
        jeHj.put("hsce",statementItemDTOS.stream().map(StatementItemPO::getDiffTaxAmount).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));

//        model.addAttribute("jeHj",jeHj);
        map.put("jeHj",jeHj);
        return map;
    }

    private void initMaterialName(StatementItemPO po , Map<String,String> materialNameMap) {
        if (materialNameMap.keySet().contains(po.getMaterialCode())) {
            po.setMaterialName(materialNameMap.get(po.getMaterialCode()));
        } else {
            ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(po.getMaterialCode(), po.getFactoryCode());
            if (Objects.nonNull(productInfoDTO)) {
                materialNameMap.put(po.getMaterialCode(), productInfoDTO.getMaterialDesc());
                po.setMaterialName(productInfoDTO.getMaterialDesc());
            }
        }
    }

    /**
     * 购销合同数据查询
     * 1.查询订货甲方信息，供货乙方信息
     * 2.查询对账单里的订单明细行
     * 3.需要生成合同编号及合同日期
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> printPurchaseSale(Long id,Integer templateType) {

        Map<String, Object> map = new HashMap<>();
        //对账单主表 可取甲乙方名称等信息
        AccountStatementDTO  accountStatementDTO = this.getDtoById(id);
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        accountStatementDTO.setCreateTimeStr(LocalDateTime.now().format(formatter1));
        accountStatementDTO.setInStockEndDateStr(DateUtil.format(accountStatementDTO.getInStockEndDate(), "yyyy-MM-dd"));
        map.put("accountStatement",accountStatementDTO);
        //查询供应商信息
        SupplierContactsDTO defaultContact = supplierClient.getDefaultContact(accountStatementDTO.getSupplierCode(), "4");
        SupplierDTO supplierDTO = supplierClient.getSupplierByCode(accountStatementDTO.getSupplierCode());
        SupplierPurchaseCategory purchaseCategory = supplierPurchaseCategoryService.getOne(new LambdaQueryWrapper<SupplierPurchaseCategory>().eq(SupplierPurchaseCategory::getSupplierId, supplierDTO.getId()), false);
        String acceptanceMethod = purchaseCategory.getAcceptanceMethod();
        DictDTO dictDTO = dictClient.getDictByTypeAndCode(DictCode.SUPPLIER_ACCETP_DEADLINE.getCode(), acceptanceMethod);
        if (ObjectUtil.isNotNull(dictDTO)){
            accountStatementDTO.setPaymentWay(dictDTO.getName());
        }

        DictDTO dictDTO1 = dictClient.getDictByTypeAndCode(DictCode.PAYMENT_WAY.getCode(), accountStatementDTO.getPaymentWay());
        if (ObjectUtil.isNotNull(dictDTO1)){
            accountStatementDTO.setPaymentWay(dictDTO1.getName());
        }

        TaxDTO taxDTO = taxClient.getByCode(accountStatementDTO.getTaxCode());
        if (ObjectUtil.isNotNull(taxDTO)){
            accountStatementDTO.setTaxName(taxDTO.getTaxName());
        }
        map.put("supplier",supplierDTO);
        map.put("supplierInvoiced",defaultContact);
        accountStatementDTO.setDifferenceAmount(accountStatementDTO.getTaxAmount().subtract(accountStatementDTO.getNotTaxAmount()));
        map.put("data",accountStatementDTO);
        map.put("nowDateStr",LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy年MM月dd日"));
        map.put("nowDate",LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd"));


        //对账单明细数据
        List<StatementItemPO> statementItemDTOS = accountStatementDetailService.findByStatementIdAndFactoryCode(id,accountStatementDTO.getFactoryCode());

               Map<String,String> materiaNameMap = new HashMap<>();
        for (StatementItemPO po : statementItemDTOS) {
            po.setTaxPriceStr(String.valueOf(po.getTaxPrice().setScale(5,RoundingMode.HALF_UP)));
            //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称，打印的时候取短描述， 2024-08-14 邓京术
            initMaterialName(po, materiaNameMap);
        }
        //materialName 物料描述 + taxPriceStr 含税单价 为唯一主键 相同的需要就那些合并累加数量和金额
        //2024-12-03新增逻辑
        List<StatementItemPO> listPO = new ArrayList<>();
        Map<String, List<StatementItemPO>> groupedMap = statementItemDTOS.stream().collect(Collectors.groupingBy(item -> item.getMaterialName() + "-" + item.getTaxPrice()));
        //重新单个汇总计算
        for (Map.Entry<String, List<StatementItemPO>> entry : groupedMap.entrySet()) {
          //  List<StatementItemPO> items = entry.getValue();
            StatementItemPO po = entry.getValue().get(0);
            BigDecimal totalTaxAmount = entry.getValue().stream()
                    .map(StatementItemPO::getTaxAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);

            // 计算 DeductionRatio 的总和（这里假设直接累加扣除比率，可能逻辑上需要调整）
//            BigDecimal totalDeductionRatio = statementItemDTOS.stream()
//                    .map(StatementItemPO::getDeductionRatio) // 假设这个方法返回 BigDecimal
//                    .filter(Objects::nonNull)
//                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //数量
            BigDecimal totalQuantity = entry.getValue().stream()
                    .map(StatementItemPO::getAsQuantity) // 假设这个方法返回 BigDecimal
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);


            // 从 TaxAmount 的总和中减去 DeductionRatio 的总和
          //  BigDecimal result = totalTaxAmount.subtract(totalDeductionRatio == null ? BigDecimal.ZERO : totalDeductionRatio);

            // 输出结果
            System.out.println("Result after deduction: " + totalTaxAmount);
            StatementItemPO newPo =  new StatementItemPO();
            newPo.setMiddleClass(po.getMiddleClass());
            newPo.setMaterialName(po.getMaterialName());
            newPo.setMaterialUnit(po.getMaterialUnit());
            newPo.setAsQuantity(totalQuantity);
            newPo.setTaxPriceStr(String.valueOf(po.getTaxPrice().setScale(5,RoundingMode.HALF_UP)));
            newPo.setTaxAmount(totalTaxAmount);
            listPO.add(newPo);
        }


//
//        List<StatementItemPO> resultList = groupedMap.entrySet().stream().map(entry -> {
//            BigDecimal totalQuantity = BigDecimal.ZERO;
//            BigDecimal totalTaxAmount = BigDecimal.ZERO;
//            for (StatementItemPO item : entry.getValue()) {
//                totalQuantity = totalQuantity.add(item.getAsQuantity());
//                totalTaxAmount = (totalTaxAmount.add(item.getTaxAmount().subtract(item.getDeductionRatio() == null ? BigDecimal.ZERO:item.getDeductionRatio())));//.setScale(2, RoundingMode.HALF_UP)
//            }
//            StatementItemPO firstItem = entry.getValue().get(0);
//            StatementItemPO po =  new StatementItemPO();
//            po.setMiddleClass(firstItem.getMiddleClass());
//            po.setMaterialName(firstItem.getMaterialName());
//            po.setMaterialUnit(firstItem.getMaterialUnit());
//            po.setAsQuantity(totalQuantity);
//            po.setTaxPriceStr(String.valueOf(firstItem.getTaxPrice().setScale(5,RoundingMode.HALF_UP)));
//            po.setTaxAmount(totalTaxAmount);
//          return po;
//        }).collect(Collectors.toList());

        BigDecimal totalTaxAmount = BigDecimal.ZERO;
//        for (StatementItemPO item : listPO) {
//            totalTaxAmount = totalTaxAmount.add(item.getTaxAmount());
//        }
        //判断日期是否是节假日
        //查询节假日list
        totalTaxAmount =  statementItemDTOS.stream().map(StatementItemPO::getTaxAmount).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        //分组后汇总含税总金额
        BigDecimal groupTotalTaxAmount = listPO.stream().map(StatementItemPO::getTaxAmount).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal tailDifference = BigDecimal.ZERO;
        if(totalTaxAmount.compareTo(groupTotalTaxAmount) != 0){
            tailDifference = totalTaxAmount.subtract(groupTotalTaxAmount).setScale(2, RoundingMode.HALF_UP);
        }

        System.out.println("Total Tax Amount: " + totalTaxAmount);
        map.put("detailList",listPO);
        JSONObject jeHj = new JSONObject();
        jeHj.put("sqje",totalTaxAmount);
        jeHj.put("wxje",tailDifference);
        jeHj.put("jedx", MoneyToChineseUtil.convertToChinese(totalTaxAmount));
        Optional<LocalDateTime> minDate = statementItemDTOS.stream()
                .map(StatementItemPO::getMvPostDate) // 提取日期
                .min(LocalDateTime::compareTo); // 找到最小日期
        LocalDateTime mainDateTime = minDate.get().minusDays(30);


        List<PublicHolidayInfo> dateList = publicHolidayInfoService.list();
        List<LocalDate> dateCollect = dateList.stream().map(PublicHolidayInfo::getHolidayTime).collect(Collectors.toList());
       // isHolidayOrWeekend(mainDateTime.toLocalDate(),dateCollect);
        LocalDate currentOrNearestWorkDay = getCurrentOrNearestWorkDay(mainDateTime.toLocalDate(), dateCollect);

        jeHj.put("dhrq", currentOrNearestWorkDay.format(formatter1));
        jeHj.put("dhrqStr", LocalDateTimeUtil.format(currentOrNearestWorkDay, "yyyy年MM月dd日"));
       // int year = LocalDate.now().getYear();
        String purchaseSaleSequenceNo = "";
        if (templateType==0){
            purchaseSaleSequenceNo = sequenceClient.getCodeSequenceNo("purchase_sale_no",8);
        }else {
            purchaseSaleSequenceNo = sequenceClient.createSequenceNo("purchase_sale_process_no");

        }
        //合同编码
        jeHj.put("contractCode",purchaseSaleSequenceNo);
        map.put("jeHj",jeHj);
        //插入文件信息表内
        //查询表中的数据，如果存在就先将之前的数据重置成已删除，如果不存在则新增
        List<AccountSalesContractsDetail> list = accountSalesContractsDetailService.list(Wrappers.lambdaQuery(AccountSalesContractsDetail.class).eq(AccountSalesContractsDetail::getAccountStatementId, accountStatementDTO.getId()));
        if(CollectionUtils.isNotEmpty(list)){
            for (AccountSalesContractsDetail detail : list){
                detail.setDelFlag("1");
            }
            accountSalesContractsDetailService.updateBatchById(list);
        }
        AccountSalesContractsDetail alesContracts = new AccountSalesContractsDetail();
        alesContracts.setAccountStatementId(accountStatementDTO.getId());//对账单id
        alesContracts.setAccountStatementNo(accountStatementDTO.getAccountStatementNo());//对账单号
        alesContracts.setContractNumber(purchaseSaleSequenceNo);
        alesContracts.setContractDate(LocalDateTime.of(currentOrNearestWorkDay,  LocalTime.of(00, 00, 0)));
        alesContracts.setDelFlag("0");//未删除
        alesContracts.setAccepPeriod(accountStatementDTO.getPaymentWay());//承兑期限
        alesContracts.setContractAmount(totalTaxAmount);//合同金额
        alesContracts.setCreateDate(LocalDateTime.now());//创建日期
        accountSalesContractsDetailService.save(alesContracts);//保存购销合同信息
        return map;
    }

    /**
     * 同一个事务下先更新再查询会有问题，故分开，并将事务隔离级别修改为 READ_COMMITTED
     * @param asIdList
     * @param asList
     */
    @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
    public void updateInvoiceCompleteFlagAuto(List<Long> asIdList,List<AccountStatement> asList){
        // 开票完成
        final List<StatementInvoicedFlagPO> flagList = accountStatementDetailService.findStatementInvoicedFlag(asIdList);
        for(StatementInvoicedFlagPO dto: flagList){
            AccountStatement as = new AccountStatement();
            as.setId(dto.getAsId());
            if(dto.getInvoicedNum().equals(dto.getItemNum())){
                as.setInvoiceCompleteFlag(1);
                asList.add(as);
            }
        }

        // 更新对账单开票标识
        if(CollectionUtils.isNotEmpty(asList)){
            accountStatementService.updateBatchById(asList);
        }

    }

    /**
     * 财务审批确认操作
     *
     * @param approveStatus 0:拒绝 1:通过
     * @param approveOpinion 审批意见
     * @param head 对账主表数据
     * @param user 当前操作人
     */
    public void financeApprove(Integer approveStatus, String approveOpinion, AccountStatementDTO head, CurrentUserDTO user,List<AttachmentManualCheck> manualCheckList) {
        head.setUpdateTime(LocalDateTime.now());
        head.setUpdateUserId(user.getUserId());
        head.setUpdateUserCode(user.getLoginName());
        head.setUpdateUserName(user.getName());
        AccountStatement accountStatement = accountStatementService.getById(head.getId());

        // 数据状态 1:暂存对账单 2:待采购确认对账单 3:采购拒绝对账单 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认对账单 8:财务驳回对账单 9:对账单已确认
        if(0 == approveStatus){
            head.setStatus(8);
            if(!accountStatementService.updateById(accountStatementConvert.DTO2Entity(head))){
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }
            this.deleteImg(head.getId());
            //财务驳回对账单，增加邮件提醒，  邮件收件人：供应商（(4)财务人员、(12)业务接口人、(5)业务经理）、对账采购组窗口
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_159", emailBis.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_159", emailFin.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_159", emailJl.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            attachmentManualCheckService.remove(new LambdaQueryWrapper<AttachmentManualCheck>()
                    .eq(AttachmentManualCheck::getBusinessType,0)
                    .eq(AttachmentManualCheck::getBusinessId,head.getId())
            );
        }else {
            head.setStatus(9);
            head.setFinanceConfirmTime(LocalDateTime.now());
            head.setFinanceConfirmUserId(LoginUtil.getUserId());
            if(!accountStatementService.updateById(accountStatementConvert.DTO2Entity(head))){
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }
            accountStatement.setFinanceConfirmTime(LocalDateTime.now());
            accountStatement.setFinanceConfirmUserId(LoginUtil.getUserId());
            List<AccountStatementDetail> asdList = accountStatementDetailService.list(Wrappers.lambdaQuery(AccountStatementDetail.class).eq(AccountStatementDetail::getAsId,head.getId()));
            AccountStatementToSapDTO accountStatementToSapDTO = makeAccountStatementSapData(3,"",accountStatement,null,asdList,null);
            SapResposeBody sapResposeBody = accountStatementSapClient.syncAccountStatement(accountStatementToSapDTO);
            if (StringUtils.isEmpty(sapResposeBody.getES_RET().getCODE())||sapResposeBody.getES_RET().getCODE().equals(RestCode.SAP_ERROR.getCode())) {
                throw new DaoException("SAP接口报错：" + sapResposeBody.getES_RET().getMSG());
            }
            //异步邮件通知 供应商 12业务接口人 4财务人员 2024-11-13 邓京术
            SupplierContactsDTO emailBis = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "12");
            SupplierContactsDTO emailFin = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "4");
            SupplierContactsDTO emailJl = supplierClient.getDefaultContact(accountStatement.getSupplierCode(), "5");

            if (Objects.nonNull(emailBis) && StringUtils.isNotEmpty(emailBis.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailBis.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            if (Objects.nonNull(emailFin) && StringUtils.isNotEmpty(emailFin.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailFin.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            //增加业务经理
            if (Objects.nonNull(emailJl) && StringUtils.isNotEmpty(emailJl.getEmail())) {
                sendEmailToSupplier("JW_POST_113", emailJl.getEmail(), accountStatement.getSupplierName(), accountStatement.getAccountStatementNo(),approveOpinion);
            }
            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(!accountStatementApproveLogic.addApproveRecord(
                head.getId(), head.getAccountStatementNo(), approveStatus, approveOpinion, 1, user
        )){
            throw new DaoException("添加对账单审批记录失败, 请联系管理员");
        }
    }

    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();
        }
    }



    /**
     * 采购审批确认操作
     *
     * @param approveStatus 0:拒绝 1:通过
     * @param approveOpinion 审批意见
     * @param head 对账主表数据
     * @param siList 对账明细数据
     * @param dsiIdList 删除的对账单明细记录ID
     * @param deductionIdList 添加的扣款记录ID
     * @param ddIdList 删除的扣款记录ID
     * @param rebateIdList 添加的返利记录ID
     * @param drIdList 删除的返利记录ID
     * @param user 当前操作人
     */
    @Transactional(rollbackFor = Exception.class)
    public String purchaseApprove(
            Integer approveStatus, String approveOpinion, AccountStatementDTO head, List<StatementItemDTO> siList,
            List<Long> dsiIdList, List<Long> deductionIdList, List<Long> ddIdList, List<Long> rebateIdList,
            List<Long> drIdList, CurrentUserDTO user,List<AttachmentManualCheck> manualCheckList
    ) {
        // 保存采购审批确认记录
        if(!accountStatementApproveLogic.addApproveRecord(head.getId(), head.getAccountStatementNo(), approveStatus, approveOpinion, 1, user)){
            throw new DaoException("添加对账单审批记录失败, 请联系管理员");
        }

        head.setUpdateTime(LocalDateTime.now());
        head.setUpdateUserId(user.getUserId());
        head.setUpdateUserCode(user.getLoginName());
        head.setUpdateUserName(user.getName());
        AccountStatement bean = accountStatementService.getById(head.getId());
        // 最终结果
        String message = "";

        // 采购审批结果 0:拒绝 1:通过
        if(0 == approveStatus){
            // 数据状态 1:暂存对账单 2:待采购确认对账单 3:采购拒绝对账单 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认对账单 8:财务驳回对账单 9:对账单已确认
            head.setStatus(3);
            // 更新对账单主表信息
            if(!accountStatementService.updateById(accountStatementConvert.DTO2Entity(head))){
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }

            this.deleteImg(head.getId());
            attachmentManualCheckService.remove(new LambdaQueryWrapper<AttachmentManualCheck>()
                    .eq(AttachmentManualCheck::getBusinessType,0)
                    .eq(AttachmentManualCheck::getBusinessId,head.getId())
            );

        }else {
            // 对账单采购确认出现差异含税单价超过±0.01 则需要推送OA审批
            boolean needPushOaFlag = false;
            // 默认单价差异范围
//            BigDecimal difRang = new BigDecimal("0.01");
            // 获取字典配置中的单价差异范围
//            final DictItemDto item = dictService.getDictDataByTypeAndItemCode("statement_invoiced_difference", "statement_difference_price");
//            if(null != item){
//                difRang = new BigDecimal(item.getItemDescription());
//            }
//
            head.setPurchaseConfirmTime(LocalDateTime.now());
            head.setPurchaseConfirmUserId(LoginUtil.getUserId());
            if(!accountStatementService.updateById(accountStatementConvert.DTO2Entity(head))){
                throw new DaoException("更新对账单主表数据失败, 请联系管理员");
            }
            BigDecimal diffAmount = BigDecimal.ZERO;
            for(StatementItemDTO si: siList){
//                if(si.getAsDiffPrice().abs().compareTo(difRang) >= 0){
//                    needPushOaFlag = true;
//                }
//
                diffAmount = si.getAsDiffAmount().add(diffAmount);
            }


            // 变更对账单相关数据
            head.setStatus(7);
            if ("1100".equals(bean.getCompanyCode())){
                head.setStatus(9);
            }
            head.setDifferenceAmount(diffAmount);
            this.dataEdit(head, siList, dsiIdList, rebateIdList, drIdList, user);

            // 对账单采购确认出现差异含税单价超过±0.01 则需要推送OA审批
            AccountStatement oldHead = accountStatementService.getById(head.getId());
            oldHead.setPushOaUserCode(null);
            oldHead.setUpdateUserName(null);
            oldHead.setPushOaNum(0);
            oldHead.setOaProcessId(null);
            oldHead.setOaProcessNo(null);
            accountStatementService.updateById(oldHead);


            this.toImg(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);
            }


        }

        return message;
    }

    /**
     * 对账单数据编辑
     *
     * @param statement 对账单主表数据
     * @param siList 对账单明细数据
     * @param dsiIdList 对账单明细删除
     * @param rebateIdList 返利记录ID集合
     * @param drId 待删除的返利记录ID集合
     * @param user 当前操作用户
     */
    @Transactional(rollbackFor = Exception.class)
    public void dataEdit(
            AccountStatementDTO statement, List<StatementItemDTO> siList, List<Long> dsiIdList, List<Long> rebateIdList,
            List<Long> drId, CurrentUserDTO user
    ) {
        // 保存对账单主表信息
        if(!accountStatementService.updateById(accountStatementConvert.DTO2Entity(statement))){
            throw new DaoException("更新对账单主表数据失败, 请联系管理员");
        }

        List<AccountStatementDetail> insertAsdList = Lists.newArrayList();
        List<AccountStatementDetail> updateAsdList = Lists.newArrayList();
        for(StatementItemDTO dto: siList){
            if(0L == dto.getId()){
                dto.setId(null);
                insertAsdList.add(dto.toAsd());
            }else {
                updateAsdList.add(dto.toAsd());
            }
        }

        List<AccountStatementDetail> allData = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(insertAsdList)){
            allData.addAll(insertAsdList);
        }
        if(CollectionUtils.isNotEmpty(updateAsdList)){
            allData.addAll(updateAsdList);
        }

        // 校验对账单明细的出入库明细数据
        List<Long> rvIdList = Lists.newArrayList();
        for(AccountStatementDetail asd: allData){
            rvIdList.add(asd.getReceiveId());
        }
        final String checkResult = receiptVoucherLogic.checkConsultVoucher(rvIdList,statement.getSupplierCode(), statement.getOrderType());
        if(StringUtils.isNotEmpty(checkResult)){
            throw new DaoException(checkResult);
        }

        // 对账单明细行号与对账单明细ID关系
        if(CollectionUtils.isNotEmpty(insertAsdList)){
            for(AccountStatementDetail asd: insertAsdList){
                asd.setCreateUserId(user.getUserId());
                asd.setCreateUserCode(user.getLoginName());
                asd.setCreateUserName(user.getName());
                asd.setCreateTime(LocalDateTime.now());
            }

            if(!accountStatementDetailService.saveBatch(insertAsdList)){
                throw new DaoException("保存新增的对账单明细数据失败, 请联系管理员");
            }
        }

        if(CollectionUtils.isNotEmpty(updateAsdList)){
            for(AccountStatementDetail asd: updateAsdList){
                asd.setUpdateUserId(user.getUserId());
                asd.setUpdateUserCode(user.getLoginName());
                asd.setUpdateUserName(user.getName());
                asd.setUpdateTime(LocalDateTime.now());
            }
            if(!accountStatementDetailService.updateBatchById(updateAsdList)){
                throw new DaoException("保存更新的对账单明细数据失败, 请联系管理员");
            }
        }


        // 删除对账单明细数据
        if(CollectionUtils.isNotEmpty(dsiIdList)){
            List<AccountStatementDetail> delAsdList = Lists.newArrayList();
            for(Long dsiId: dsiIdList){
                AccountStatementDetail delAsd = new AccountStatementDetail();
                delAsd.setId(dsiId);
                delAsd.setDeleteFlag(1);
                delAsd.setItemNo("00000");
                delAsdList.add(delAsd);
            }

            if(!accountStatementDetailService.updateBatchById(delAsdList)){
                throw new DaoException("删除对账单明细数据失败, 请联系管理员");
            }
        }

        // 更新对账单明细行号
        accountStatementDetailService.updateDetailItemNo(statement.getId());
    }

    /**
     * 修改付款备注
     * @param id
     * @param paymentRemark
     */
    @Transactional(rollbackFor = Exception.class)
    public void savePaymentRemark(Long id, String paymentRemark) {
        AccountStatement accountStatement = accountStatementService.getById(id);
        accountStatement.setUpdateTime(LocalDateTime.now());
        accountStatement.setUpdateUserName(LoginUtil.getAccount());
        accountStatement.setPaymentRemark(StringUtils.isNotEmpty(paymentRemark)?paymentRemark:"");
        accountStatementService.updateById(accountStatement);
    }

    @Override
    public void toImg(Long asId) {
        AccountStatement accountStatement = accountStatementService.getById(asId);
        List<BusinessAttachmentDTO> accountStatementAttachments =  getImgList(asId);
        List<String> fileList = new ArrayList<>();
        if (CollUtil.isNotEmpty(accountStatementAttachments)){
            KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
            kingdeeInvoiceCloudImageDTO.setImageCode(StrUtil.isNotEmpty(accountStatement.getImgCode())?accountStatement.getImgCode():sequenceClient.createSequenceNo("image_code"));
            if (CollUtil.isNotEmpty(accountStatementAttachments)){
                kingdeeInvoiceCloudImageDTO.setBusinessAttachmentList(accountStatementAttachments);
                KingdeeInvoiceCloudImageDTO result = kingdeeImageLogic.pushImage(kingdeeInvoiceCloudImageDTO);
                accountStatementService.update(new LambdaUpdateWrapper<AccountStatement>().set(AccountStatement::getImgCode,result.getImageCode()).set(AccountStatement::getImgTime,LocalDateTime.now()).set(AccountStatement::getImgUserId,LoginUtil.getUserId())
                        .eq(AccountStatement::getId,asId));
                //更新附件影像
                accountStatementAttachments.forEach(businessAttachmentDTO -> {
                    if (businessAttachmentDTO.getType().equals("account_statement")) {
                        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()));
                    }
                });
            }

        }
    }

    @Override
    public List<BusinessAttachmentDTO>  getImgList(Long id) {
        AccountStatement accountStatement = accountStatementService.getById(id);
        //影像化
        List<BusinessAttachmentDTO> accountStatementAttachments = businessAttachmentLogic.getListByBusinessId(id);

        List<String> fileList = new ArrayList<>();
        if (StringUtils.isNotEmpty(accountStatement.getFiles())){
            fileList.addAll(Arrays.asList(accountStatement.getFiles().split(",")));
        }
        if (CollUtil.isNotEmpty(fileList)) {
            DictDTO dictDTO = dictClient.getDictByTypeAndCode("businessFileType", "account");
            List<FileResposeCDTO> fileResposeCDTOList = fileClient.getFileInfos(fileList);
            fileResposeCDTOList.forEach(file -> {
                BusinessAttachmentDTO businessAttachmentDTO = new BusinessAttachmentDTO();
                businessAttachmentDTO.setFileId(file.getId());
                businessAttachmentDTO.setImageFileId(file.getImageFileId());
                businessAttachmentDTO.setType("account_statement");
                businessAttachmentDTO.setSort(ObjectUtil.isNotNull(dictDTO)?dictDTO.getSort():null);
                businessAttachmentDTO.setFileName(file.getFileName());
                accountStatementAttachments.add(businessAttachmentDTO);
            });
        }
        //accountStatementAttachments中按照sort从小到大排序
        accountStatementAttachments.sort(
                Comparator.nullsLast(Comparator.comparing(BusinessAttachmentDTO::getSort)));

        return accountStatementAttachments;
    }

    @Override
    public void deleteImg(Long asId) {
        AccountStatement accountStatement = accountStatementService.getById(asId);
        if (ObjectUtil.isNull(accountStatement.getImgTime())){
            return;
        }
        KingdeeInvoiceCloudImageDTO kingdeeInvoiceCloudImageDTO = new KingdeeInvoiceCloudImageDTO();
        kingdeeInvoiceCloudImageDTO.setImageCode(accountStatement.getImgCode());
        kingdeeImageLogic.deleteAllImage(kingdeeInvoiceCloudImageDTO);
        //删除影像化
        List<BusinessAttachment> accountStatementAttachments = businessAttachmentService.list(new LambdaQueryWrapper<BusinessAttachment>().eq(BusinessAttachment::getBusinessId,asId));
        if (CollUtil.isNotEmpty(accountStatementAttachments)){
            //过滤出accountStatementAttachments中存在imageCode的数据
            List<BusinessAttachment> accountStatementAttachmentsImageCode = accountStatementAttachments.stream().filter(accountStatementAttachment -> StringUtils.isNotEmpty(accountStatementAttachment.getImageCode())).toList();

            if (CollUtil.isNotEmpty(accountStatementAttachmentsImageCode)){
                accountStatementService.update(new LambdaUpdateWrapper<AccountStatement>()
//                        .set(AccountStatement::getImgCode,null)
                        .set(AccountStatement::getImgTime,null)
                        .set(AccountStatement::getImgUserId,null)
                        .eq(AccountStatement::getId,asId));
//                accountStatementAttachmentService.update(new LambdaUpdateWrapper<AccountStatementAttachment>().set(AccountStatementAttachment::getImageCode,null).set(AccountStatementAttachment::getImagePath,null)
//                        .eq(AccountStatementAttachment::getAsId,asId));
            }
        }
    }

    //传入一个日期进行节假日判断，返回一个最近的工作日日期

    // 检查给定日期是否是节假日或周末
    private boolean isHolidayOrWeekend(LocalDate date,List<LocalDate> holidayDates) {
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        // 周末：周六和周日
        if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) {
            return true;
        }
        // 节假日
        return holidayDates.contains(date);
    }

    // 获取当前日期或最近的工作日
    private  LocalDate getCurrentOrNearestWorkDay(LocalDate date,List<LocalDate> holidayDates) {
        while (isHolidayOrWeekend(date,holidayDates)) {
            date = date.minusDays(1);
        }
        return date;
    }

    //获取对账模块供应商对应多个对账采购组配置数据
/*    public List<StatementPaymentSetting> findStatementPaymentSetting(String supplierCode){
        //获取当前登录用户id
        //获取登录用户默认采购组code
        Long userId = LoginUtil.getUserId();
        final LambdaQueryWrapper<UserPurchaseGroup> userPurchaseGroupLambdaQueryWrapper =
                new LambdaQueryWrapper<UserPurchaseGroup>().eq(
                        UserPurchaseGroup::getUserId,userId).eq(UserPurchaseGroup::getMark,1);
        final UserPurchaseGroup userPurchaseGroup = userPurchaseGroupService.getOne(userPurchaseGroupLambdaQueryWrapper);
        if(userPurchaseGroup != null){
            final LambdaQueryWrapper<PurchaseGroup> purchaseGroupLambdaQueryWrapper =
                    new LambdaQueryWrapper<PurchaseGroup>().eq(
                                    PurchaseGroup::getDeleteFlag, DelFlag.NORMAL.getStatus()).eq(PurchaseGroup::getId,userPurchaseGroup.getPurchaseGroupId());
            PurchaseGroup purchaseGroup = purchaseGroupService.getOne(purchaseGroupLambdaQueryWrapper);
            if(purchaseGroup != null){
                return statementPaymentSettingService.findStatementPaymentSettingList(userId,purchaseGroup.getPurchaseGroupCode(),supplierCode);
            }
        }
    return null;
    }*/
}
