package com.jwipc.finance.logic.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.constant.DictCode;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.convert.PaymentPlanConvert;
import com.jwipc.finance.convert.PaymentPlanDetailConvert;
import com.jwipc.finance.dto.PaymentPlanDTO;
import com.jwipc.finance.dto.PaymentPlanItemDTO;
import com.jwipc.finance.entity.*;
import com.jwipc.finance.logic.PaymentPlanLogic;
import com.jwipc.finance.model.po.AccountStatementPO;
import com.jwipc.finance.model.po.CreatePcaDetailPO;
import com.jwipc.finance.model.po.PaymentPlanDetailPO;
import com.jwipc.finance.model.po.PaymentPlanPO;
import com.jwipc.finance.model.query.AccountStatementQuery;
import com.jwipc.finance.model.query.PaymentPlanQuery;
import com.jwipc.finance.service.*;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.sys.client.*;
import com.jwipc.sys.client.dto.DictDTO;
import com.jwipc.util.DateUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author 邓京术
 * @date 2025/07/22 11:39
 * @desc
 */
@Service
@RequiredArgsConstructor
public class PaymentPlanLogicImpl implements PaymentPlanLogic {
    private final PaymentPlanConvert paymentPlanConvert;
    private final PaymentPlanDetailConvert paymentPlanDetailConvert;
    private final IPaymentPlanService paymentPlanService;
    private final IPaymentPlanApproveService paymentPlanApproveService;
    private final IPaymentPlanDetailService paymentPlanDetailService;
    private final IPaymentPlanSummaryService paymentPlanSummaryService;
    private final IInvoicedApplyDetailService invoicedApplyDetailService;
    private final SequenceClient sequenceClient;
    private final IAccountStatementService accountStatementService;
    private final DictClient dictClient;
    @Override
    public PageView findByPage(PaymentPlanQuery query) {
        final Page<PaymentPlan> dbPage = PageUtil.toPage(query);
        List<PaymentPlanPO> PaymentPlanPOS = paymentPlanService.findPageByQuery(dbPage, query);
        List<PaymentPlanDTO> PaymentPlanDTOS = paymentPlanConvert.po2PageListDTO(PaymentPlanPOS);
        return PageUtil.getPV(PaymentPlanDTOS, dbPage.getTotal());
    }

    @Override
    public List<PaymentPlanDTO> listAll(PaymentPlanQuery query) {
        List<PaymentPlanPO> PaymentPlanPOS = paymentPlanService.findPageByQuery(null, query);
        List<PaymentPlanDTO> PaymentPlanDTOS = paymentPlanConvert.po2PageListDTO(PaymentPlanPOS);
        return PaymentPlanDTOS;
    }

    @Override
    public PaymentPlanDTO getById(Long id) {
        PaymentPlan PaymentPlan = paymentPlanService.getById(id);
        return paymentPlanConvert.entity2DTO(PaymentPlan);
    }
    @Override
    public PaymentPlanDTO getDtoById(Long id) {
        PaymentPlanPO PaymentPlan = paymentPlanService.selectPoById(id);
        PaymentPlanDTO PaymentPlanDTO = paymentPlanConvert.poy2DTO(PaymentPlan);
        return PaymentPlanDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void addNewPaymentPlan(String paymentPlanYear,String paymentPlanMonth,boolean flag) {
        //检查数据库是否已经存在当月付款计划单
        LambdaQueryWrapper<PaymentPlan> paymentPlanLambdaQueryWrapper = new LambdaQueryWrapper<>();
        paymentPlanLambdaQueryWrapper.eq(PaymentPlan::getPaymentPlanYear, paymentPlanYear).eq(PaymentPlan::getPaymentPlanMonth,paymentPlanMonth);
        PaymentPlan paymentPlanTemp = paymentPlanService.getOne(paymentPlanLambdaQueryWrapper);
        if (Objects.nonNull(paymentPlanTemp)) {
            throw new DaoException("当前付款计划月份已经存在，请检查!");
        }
        AccountStatementQuery query = new AccountStatementQuery();
        query.setAccountStatementYear(paymentPlanYear + "" + paymentPlanMonth);
        List<AccountStatementPO> accountOrApplyList = accountStatementService.findAccountStatementByYM(query);
        final String no = "YSD" + paymentPlanYear + paymentPlanMonth + "01";

        //查询字典表，付款计划汇总是否需要按维度查询
        final List<DictDTO> paymentWayList = dictClient.getDicByType(DictCode.PAYMENT_PLAN_TYPE.getCode());
        String paymentPLanType = paymentWayList.get(0).getCode();

        // 对账单主表
        PaymentPlan paymentPlan = new PaymentPlan();
        paymentPlan.setPaymentPlanNo(no);
        paymentPlan.setStatus(1);
        paymentPlan.setPaymentPlanYear(paymentPlanYear);
        paymentPlan.setPaymentPlanMonth(paymentPlanMonth);
        paymentPlan.setCreateTime(LocalDateTime.now());
        if (flag) {
            paymentPlan.setCreateUserId(LoginUtil.getUserId());
            paymentPlan.setCreateUserCode(LoginUtil.getAccount());
            paymentPlan.setCreateUserName(LoginUtil.getName());
        } else {
            paymentPlan.setCreateUserId(1L);
            paymentPlan.setCreateUserCode("admin");
            paymentPlan.setCreateUserName("admin");
        }
        paymentPlan.setDeleteFlag(0);
        paymentPlan.setPlanType(paymentPLanType);
        paymentPlanService.saveOrUpdate(paymentPlan);

        List<PaymentPlanDetail> paymentPlanDetails = Lists.newArrayList();
        for(AccountStatementPO accountStatementPO: accountOrApplyList) {
            //发票资料交接页面，实际未付金额fin_invoiced_apply ActualUnpaidAmount
            BigDecimal actualUnpaidAmount = accountStatementPO.getActualUnpaidAmount();
            if (actualUnpaidAmount == null || actualUnpaidAmount.floatValue() == 0) {
                BigDecimal invoiceTaxTotalAmount = accountStatementPO.getInvoiceTaxTotalAmount();
                BigDecimal invoiceTaxAmount = accountStatementPO.getInvoiceTaxAmount();
                BigDecimal strikePriceAmount = accountStatementPO.getStrikePriceAmount();
                if (accountStatementPO.getCurrencyCode().equals("CNY")) {
                    actualUnpaidAmount = invoiceTaxTotalAmount.subtract(strikePriceAmount);
                } else {
                    actualUnpaidAmount = invoiceTaxAmount.subtract(strikePriceAmount);
                }
            }

            List<CreatePcaDetailPO>  createPcaDetailPOS = invoicedApplyDetailService.queryCodApplyInvoiceListByAccountStatementNo(accountStatementPO.getAccountStatementNo(),null);
            //计算付款申请明细中的本次申请金额
//            BigDecimal budOutMoneySum = BigDecimal.ZERO;
            BigDecimal appliedUnpaidAmountHis = BigDecimal.ZERO;//已请款未付总额

            BigDecimal finishMoneySum = BigDecimal.ZERO;//已经付款完成的合计
            //统计未付金额及应付金额
            for (CreatePcaDetailPO createPcaDetailPO : createPcaDetailPOS) {
//                budOutMoneySum = budOutMoneySum.add(createPcaDetailPO.getBudOutMoney());
                //排除已经付款完成的  fin_payment_cod_apply 付款申请主表 status == 5（付款完成） 或者是(承兑汇票类型 且在oa审批中 也算付款完成)
                if (createPcaDetailPO.getStatus() != null && (createPcaDetailPO.getStatus() == 5 || (createPcaDetailPO.getStatus() == 3 && createPcaDetailPO.getPaymentWayDesc().equals("承兑汇票")))) {
                    //付款完成的累加
                    finishMoneySum = finishMoneySum.add(createPcaDetailPO.getBudOutMoney());
                } else {
                    appliedUnpaidAmountHis = appliedUnpaidAmountHis.add(createPcaDetailPO.getBudOutMoney());
                }
            }
            //开票申请中的“实际未付金额fin_invoiced_apply actual_unpaid_amount - 所有此对账单的付款申请中的本次申请金额累加， 申请明细字段fin_payment_cod_apply_detail bud_out_money
            BigDecimal totalUnpaidAmount = actualUnpaidAmount.subtract(finishMoneySum);
            //应付金额=0， 且已请款未付金额也等于0，则忽略， 已请款未付金额不等于0，则要作付款计划
            if (totalUnpaidAmount.compareTo(BigDecimal.ZERO) == 0 && appliedUnpaidAmountHis.compareTo(BigDecimal.ZERO) == 0) continue;

            PaymentPlanDetail paymentPlanDetail = new PaymentPlanDetail();
            paymentPlanDetail.setAppliedUnpaidAmount(appliedUnpaidAmountHis);
            //设置应付金额 = 发票实际未付金额(actualUnpaidAmount) - 申请单已经付款完成的金额(finishMoneySum)
            paymentPlanDetail.setActualPayAmount(actualUnpaidAmount.subtract(finishMoneySum));
            //根据付款计划单月份 顺序流水
            final String itemNo = sequenceClient.getCodeSequenceNo(paymentPlan.getPaymentPlanNo() , "payment_plan_code",1);
            paymentPlanDetail.setPaymentPlanDetailNo(Integer.parseInt(itemNo));
            if (flag) {
                paymentPlanDetail.setCreateUserId(LoginUtil.getUserId());
                paymentPlanDetail.setCreateUserCode(LoginUtil.getAccount());
                paymentPlanDetail.setCreateUserName(LoginUtil.getName());
            } else {
                paymentPlanDetail.setCreateUserId(1L);
                paymentPlanDetail.setCreateUserCode("admin");
                paymentPlanDetail.setCreateUserName("admin");
            }
            paymentPlanDetail.setCreateTime(LocalDateTime.now());
            paymentPlanDetail.setPaymentPlanId(paymentPlan.getId());
            paymentPlanDetail.setPaymentPlanNo(paymentPlan.getPaymentPlanNo());
            paymentPlanDetail.setStatus(1);
            paymentPlanDetail.setAccountStatementNo(accountStatementPO.getAccountStatementNo());
            paymentPlanDetail.setAccountStatementYear(accountStatementPO.getAccountStatementYear());
            paymentPlanDetail.setAccountStatementMonth(accountStatementPO.getAccountStatementMonth());
            paymentPlanDetail.setCompanyCode(accountStatementPO.getCompanyCode());
            paymentPlanDetail.setSupplierCode(accountStatementPO.getSupplierCode());
            paymentPlanDetail.setSupplierName(accountStatementPO.getSupplierName());
            paymentPlanDetail.setCurrencyCode(accountStatementPO.getCurrencyCode());
            paymentPlanDetail.setPurchaseGroup(accountStatementPO.getPurchaseGroup());
            paymentPlanDetail.setPaymentWay(accountStatementPO.getPaymentWay());
            paymentPlanDetail.setPaymentExpireDate(accountStatementPO.getPaymentExpireDate());
            paymentPlanDetail.setPaymentTermCode(accountStatementPO.getPaymentTermCode());
            paymentPlanDetail.setDeleteFlag(0);
            paymentPlanDetail.setPaymentType("D");
            paymentPlanDetails.add(paymentPlanDetail);
        }
        if(!paymentPlanDetailService.saveBatch(paymentPlanDetails)){
            throw new DaoException("保存付款单明细数据失败, 请联系管理员");
        }
    }

    /**
     * 付款计划明细单编辑时保存
     *
     * @param optType      操作类型；1-编辑；2-查看；3-主管确认；4-财务确认
     * @param headData      对账单抬头数据
     * @param statementItem 对账单明细数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void saveOrUpdate(Integer optType, String headData, String statementItem) {
        if(StringUtils.isEmpty(headData)) {
            throw new DaoException("参数错误, 请检查");
        }
        if(StringUtils.isEmpty(statementItem)){
            throw new DaoException("对账单明细数据错误, 请检查");
        }
        final List<PaymentPlanItemDTO> siList = JSONArray.parseArray(statementItem, PaymentPlanItemDTO.class);
        // 付款计划单主表
        PaymentPlan paymentPlan = JSONObject.parseObject(headData, PaymentPlan.class);

        List<PaymentPlanDetail> asdList = Lists.newArrayList();
        for(PaymentPlanItemDTO dto: siList) {
            //如果执行的是删除操作
            if (dto.getDeleteFlag() != null && dto.getDeleteFlag() == -1) {
                PaymentPlanDetail asd = new PaymentPlanDetail();
                asd.setId(dto.getId());
                asd.setDeleteFlag(1);
                asd.setStatus(3);
                if (StringUtils.isEmpty(dto.getRemark())) {
                    throw new DaoException("删除原因不能为空");
                }
                asd.setRemark(dto.getRemark());
                asdList.add(asd);
                continue;
            }

            PaymentPlanDetail asd = dto.toAsd();
            asd.setPaymentPlanId(paymentPlan.getId());
            asd.setPaymentPlanNo(paymentPlan.getPaymentPlanNo());
            if (asd.getId() == 0 ) {
                final String itemNo = sequenceClient.getCodeSequenceNo(paymentPlan.getPaymentPlanNo() , "payment_plan_code",1);
                asd.setPaymentPlanDetailNo(Integer.parseInt(itemNo));
                asd.setCreateUserId(LoginUtil.getUserId());
                asd.setCreateUserCode(LoginUtil.getAccount());
                asd.setCreateUserName(LoginUtil.getName());
                asd.setCreateTime(LocalDateTime.now());
                asd.setNewSign("X");
            } else {
                PaymentPlanDetail db = paymentPlanDetailService.getById(asd.getId());
                asd.setUpdateUserId(LoginUtil.getUserId());
                asd.setUpdateUserCode(LoginUtil.getAccount());
                asd.setUpdateUserName(LoginUtil.getName());
                asd.setUpdateTime(LocalDateTime.now());
                if (null == db.getNewSign()) {
                    asd.setCurrencyCode(db.getCurrencyCode());
                    asd.setCompanyCode(db.getCompanyCode());
                    asd.setSupplierCode(db.getSupplierCode());
                    asd.setSupplierName(db.getSupplierName());
                    //预付款的可以修改
//                    asd.setPaymentWay(db.getPaymentWay());
                    asd.setPaymentTermCode(db.getPaymentTermCode());
                    asd.setPurchaseGroup(db.getPurchaseGroup());
                }
            }
            //校验对账单号不能重复
            if (StringUtils.isNotEmpty(asd.getAccountStatementNo())) {
                PaymentPlanQuery paymentPlanQuery = new PaymentPlanQuery();
                paymentPlanQuery.setPpId(String.valueOf(paymentPlan.getId()));
//                paymentPlanQuery.setDelFlag(0);不需要查未删除的。
                paymentPlanQuery.setAccountStatementNo(asd.getAccountStatementNo());
                List<PaymentPlanDetailPO> paymentPlanDetailPOS = paymentPlanDetailService.findByPaymentPlanId(paymentPlanQuery);
                if (asd.getId() == 0) {
                    if(null != paymentPlanDetailPOS && paymentPlanDetailPOS.size() >= 1) {
                        throw new DaoException("对账单号：" + asd.getAccountStatementNo() + "不能重复");
                    }
                } else {
                    if(null != paymentPlanDetailPOS && paymentPlanDetailPOS.size() >= 1 && !paymentPlanDetailPOS.get(0).getId().equals(asd.getId())) {
                        throw new DaoException("对账单号：" + asd.getAccountStatementNo() + "不能重复");
                    }
                }

                //校验供应商，公司，付款方式，侍类型，对账单年月，是不是一致
//                if (asd.getId() == 0 ) {
                    AccountStatementQuery query = new AccountStatementQuery();
                    query.setStatementNo(asd.getAccountStatementNo());
                    List<AccountStatementPO> accountStatementPOList = accountStatementService.accountOrApplyListByNo(query);
                    if (null == accountStatementPOList || accountStatementPOList.size() <= 0) {
                        throw new DaoException("对账单号：" + asd.getAccountStatementNo() + "不存在");
                    }
                    AccountStatementPO temp = accountStatementPOList.get(0);
                    asd.setAccountStatementYear(temp.getAccountStatementYear());
                    asd.setAccountStatementMonth(temp.getAccountStatementMonth());

                    if (!temp.getSupplierCode().equals(asd.getSupplierCode())) {
                        throw new DaoException("供应商编码：" + asd.getSupplierCode() + "与原对账单号的供应商编码: "+temp.getSupplierCode()+"不一致。");
                    }
                    if (!temp.getCompanyCode().equals(asd.getCompanyCode())) {
                        throw new DaoException("公司：" + asd.getCompanyCode() + "与原对账单号的公司: "+temp.getCompanyCode()+"不一致。");
                    }
                    if (!temp.getCurrencyCode().equals(asd.getCurrencyCode())) {
                        throw new DaoException("货币：" + asd.getCurrencyCode() + "与原对账单号的货币: "+temp.getCurrencyCode()+"不一致。");
                    }
                    if (!temp.getPaymentWay().equals(asd.getPaymentWay())) {
//                        throw new DaoException("付款方式：" + asd.getPaymentWay() + "与原对账单号的付款方式: "+temp.getPaymentWay()+"不一致。");
                    }
                    if (!temp.getPaymentTermCode().equals(asd.getPaymentTermCode())) {
                        throw new DaoException("付款条件：" + asd.getPaymentTermCode() + "与原对账单号的付款条件: "+temp.getPaymentTermCode()+"不一致。");
                    }
                    if (!temp.getPurchaseGroup().equals(asd.getPurchaseGroup())) {
                        throw new DaoException("采购组：" + asd.getPurchaseGroup() + "与原对账单号的采购组: "+temp.getPurchaseGroup()+"不一致。");
                    }
//                }
                //计算上月已申请，未付款的金额放到未付金额（历史）
                List<CreatePcaDetailPO>  createPcaDetailPOS = invoicedApplyDetailService.queryCodApplyInvoiceListByAccountStatementNo(asd.getAccountStatementNo(), paymentPlan.getPaymentPlanYear() + paymentPlan.getPaymentPlanMonth());
                BigDecimal appliedUnpaidAmountHis = BigDecimal.ZERO;
                //统计未付金额及应付金额
                for (CreatePcaDetailPO createPcaDetailPO : createPcaDetailPOS) {
                    //排除已经付款完成的  fin_payment_cod_apply 付款申请主表 status == 5 或者是(承兑汇票类型 且在oa审批中 也算付款完成)
                    if (createPcaDetailPO.getStatus() != null && (createPcaDetailPO.getStatus() == 5 || (createPcaDetailPO.getStatus() == 3 && createPcaDetailPO.getPaymentWayDesc().equals("承兑汇票")))) {
                        //付款完成的累加
                    } else {
                        appliedUnpaidAmountHis = appliedUnpaidAmountHis.add(createPcaDetailPO.getBudOutMoney());
                    }
                }
                asd.setAppliedUnpaidAmount(appliedUnpaidAmountHis);
            } else {
                //计算上月已申请，未付款的金额放到未付金额（历史）
                AccountStatementQuery accountStatementQuery = new AccountStatementQuery();
                accountStatementQuery.setSupplierCode(asd.getSupplierCode());
                accountStatementQuery.setCompanyCode(asd.getCompanyCode());
                accountStatementQuery.setAccountStatementYear(paymentPlan.getPaymentPlanYear() + paymentPlan.getPaymentPlanMonth());
                List<AccountStatementPO> accountStatementPOS = accountStatementService.findAccountStatementBySupplierCodeS2(accountStatementQuery);
                //计算总额
                final BigDecimal[] budOutMoney = {BigDecimal.ZERO};
                accountStatementPOS.stream().forEach(oo -> {
                    //排除已经付款完成的  fin_payment_advance_apply 付款申请主表 status == 5
                    if (oo.getStatus() != null && oo.getStatus() == 5) {
                        //付款完成的累加
                    } else if (null != oo.getActualUnpaidAmount()) {
                        budOutMoney[0] = budOutMoney[0].add(oo.getActualUnpaidAmount());
                    }
                });
                asd.setAppliedUnpaidAmount(budOutMoney[0]);
            }
            asdList.add(asd);
        }

        if(!paymentPlanDetailService.saveOrUpdateBatch(asdList)){
            throw new DaoException("保存付款单明细数据失败, 请联系管理员");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void approveOperation(Integer optType, String headData) {
        if(StringUtils.isEmpty(headData)) {
            throw new DaoException("参数错误, 请检查");
        }
        // 对账单主表
        //对账单数据状态 1:暂存 2:待采购主管确认 3:采购拒绝 4:待财务确认 5:财务驳回 6:已发布
        PaymentPlan paymentPlan = JSONObject.parseObject(headData, PaymentPlan.class);
        //保存审批记录
        PaymentPlanApprove paymentPlanApprove = new PaymentPlanApprove();
        //采购主管确认 3 optType == 4 财务审批
        if (optType == 3) {
            paymentPlan.setStatus(4);
            paymentPlanApprove.setApproveNode(1);
            paymentPlanApprove.setApproveResult(1);
            //查询未删除的明细数据，是否有未提交的，如果存在则报错
            PaymentPlanQuery paymentPlanQuery = new PaymentPlanQuery();
            paymentPlanQuery.setPpId(String.valueOf(paymentPlan.getId()));
            paymentPlanQuery.setDelFlag(0);
            paymentPlanQuery.setStatus(1);
            List<PaymentPlanDetailPO> paymentPlanDetailPOS = paymentPlanDetailService.findByPaymentPlanId(paymentPlanQuery);
            if (!paymentPlanDetailPOS.isEmpty()) {
                throw new DaoException("还有未提交的明细数据，请检查");
            }
            //财务确认
        } else if (optType == 4) {
            paymentPlanApprove.setApproveNode(2);
            //财务驳回
            if (paymentPlan.getStatus() == 5) {
                paymentPlan.setStatus(5);
                paymentPlanApprove.setApproveResult(3);
                //财务 通过
            } else if (paymentPlan.getStatus() == 4) {
                paymentPlan.setStatus(6);
                paymentPlanApprove.setApproveResult(1);
            }

            //optType == 5 财务审批拒绝
        } else if (optType == 5) {
            //财务驳回
            paymentPlan.setStatus(5);
            //保存审批日志
            paymentPlanApprove.setApproveNode(2);
            paymentPlanApprove.setApproveResult(3);
        }
        paymentPlanApprove.setApproveOpinion(paymentPlan.getRemark());


        //如果是采购主管确认，则要生成付款计划汇总数据，先删除在存入
        PaymentPlanQuery paymentPlanQuery = new PaymentPlanQuery();
        paymentPlanQuery.setPpId(String.valueOf(paymentPlan.getId()));
        List<PaymentPlanDetailPO> paymentPlanDetailPOS = paymentPlanDetailService.findByPaymentPlanId(paymentPlanQuery);
        List<PaymentPlanItemDTO> list = paymentPlanDetailConvert.po2DtoList(paymentPlanDetailPOS);
        PaymentPlan paymentPlanDb = paymentPlanService.getById(paymentPlan.getId());
        paymentPlan.setRemark(paymentPlanDb.getRemark());//还原备注
        paymentPlanApprove.setPpId(paymentPlanDb.getId());
        paymentPlanApprove.setPpNo(paymentPlanDb.getPaymentPlanNo());
        paymentPlanApprove.setApproveUserId(LoginUtil.getUserId());
        paymentPlanApprove.setApproveUserCode(LoginUtil.getAccount());
        paymentPlanApprove.setApproveUserName(LoginUtil.getName());
        paymentPlanApprove.setApproveTime(LocalDateTime.now());

        List<PaymentPlanSummary> paymentPlanSummaryList = Lists.newArrayList();
//        List<PaymentPlanSummaryTwo> paymentPlanSummaryTwoList = Lists.newArrayList();
        Map<String,String> supplierCompanyMap = Maps.newHashMap();
        //采购主管确认付款计划
        if (optType == 3) {
            list.stream().forEach(itemDTO -> {
                //已经删除的明细不计算在内。
                if (itemDTO.getDeleteFlag() == 0) {
                    String key = itemDTO.getSupplierCode() + itemDTO.getCompanyCode() + itemDTO.getPaymentType();
                    if (supplierCompanyMap.keySet().contains(key)) {
                        paymentPlanSummaryList.stream().forEach(item -> {
                            String tempKey = item.getSupplierCode() + item.getCompanyCode() + item.getPaymentType();
                            if (key.equals(tempKey)) {
                                //应付金额 累加
                                item.setActualPayAmount(item.getActualPayAmount().add(itemDTO.getActualPayAmount() == null ? BigDecimal.ZERO : itemDTO.getActualPayAmount()));
                                //已请款未付金额（历史） 明细数据累加
                                item.setAppliedUnpaidAmount(item.getAppliedUnpaidAmount().add(itemDTO.getAppliedUnpaidAmount() == null ? BigDecimal.ZERO : itemDTO.getAppliedUnpaidAmount()));
                            }
                        });
                    } else {
                        supplierCompanyMap.put(key, key);
                        PaymentPlanSummary paymentPlanSummary = new PaymentPlanSummary();
                        paymentPlanSummary.setPaymentPlanNo(paymentPlanDb.getPaymentPlanNo());
                        paymentPlanSummary.setPaymentPlanId(paymentPlanDb.getId());
                        paymentPlanSummary.setSupplierCode(itemDTO.getSupplierCode());
                        paymentPlanSummary.setSupplierName(itemDTO.getSupplierName());
                        paymentPlanSummary.setCurrencyCode(itemDTO.getCurrencyCode());
                        paymentPlanSummary.setCompanyCode(itemDTO.getCompanyCode());
                        paymentPlanSummary.setCompanyName(itemDTO.getCompanyName());
                        //应付金额
                        paymentPlanSummary.setActualPayAmount(itemDTO.getActualPayAmount() == null ? BigDecimal.ZERO : itemDTO.getActualPayAmount());
                        paymentPlanSummary.setAppliedUnpaidAmount(itemDTO.getAppliedUnpaidAmount() == null ? BigDecimal.ZERO : itemDTO.getAppliedUnpaidAmount());

                        paymentPlanSummary.setAppliedPaymentAmount(BigDecimal.ZERO);
//            paymentPlanSummary.setDifferenceAmount(itemDTO.getActualPayAmount());
//            differencePercent
                        paymentPlanSummary.setPaidAmountMonth(BigDecimal.ZERO);
                        paymentPlanSummary.setPaymentType(itemDTO.getPaymentType());
                        paymentPlanSummary.setCreateUserId(LoginUtil.getUserId());
                        paymentPlanSummary.setCreateUserCode(LoginUtil.getAccount());
                        paymentPlanSummary.setCreateUserName(LoginUtil.getName());
                        paymentPlanSummary.setCreateTime(LocalDateTime.now());
                        paymentPlanSummaryList.add(paymentPlanSummary);
                    }
                }
            });
        }
        paymentPlanApproveService.save(paymentPlanApprove);
        if (optType == 3) {
            paymentPlanSummaryService.remove(Wrappers.lambdaQuery(PaymentPlanSummary.class).eq(PaymentPlanSummary::getPaymentPlanId, paymentPlanDb.getId()));
            if(!paymentPlanSummaryService.saveOrUpdateBatch(paymentPlanSummaryList)){
                throw new DaoException("保存付款汇总数据失败, 请联系管理员");
            }
        }
        if(!paymentPlanService.saveOrUpdate(paymentPlan)){
            throw new DaoException("保存付款计划明细数据失败, 请联系管理员");
        }
    }

    @Override
    @Transactional
    public void dataDel(String ids, Integer type) {
        final List<String> idList = Arrays.asList(ids.split(","));
        List<PaymentPlanDetail> details = paymentPlanDetailService.list(Wrappers.lambdaQuery(PaymentPlanDetail.class).in(PaymentPlanDetail::getId, idList));
        List<PaymentPlanDetail> detailDel = Lists.newArrayList();
        details.stream().forEach(item -> {
//            item.setUpdateTime(LocalDateTime.now());
//            item.setUpdateUserId(LoginUtil.getUserId());
//            item.setUpdateUserCode(LoginUtil.getAccount());
//            item.setUpdateUserName(LoginUtil.getName());
            PaymentPlanDetail paymentPlanDetail = new PaymentPlanDetail();
            paymentPlanDetail.setId(item.getId());
            if (0 == type ) {
                paymentPlanDetail.setDeleteFlag(0);
                paymentPlanDetail.setStatus(1);
            } else {
                paymentPlanDetail.setDeleteFlag(1);
                paymentPlanDetail.setStatus(3);
            }
            detailDel.add(paymentPlanDetail);
        });
        String error = "对账单明细删除失败, 请联系管理员";
        if (type == 0) {
            error = "对账单明细恢复删除失败, 请联系管理员";
        }

        if (detailDel == null || detailDel.size() <= 0) {
//            throw new DaoException("没有要删除的数据.");
        } else if(!paymentPlanDetailService.updateBatchById(detailDel)){
            throw new DaoException(error);
        }
    }

    /**
     * 提交对账单进行确认
     *
     * @param ids 对账单ID集合
     */
    @Override
    @Transactional
    public void submitConfirm(String ids) {
        final List<String> idList = Arrays.asList(ids.split(","));
        List<PaymentPlanDetail> details = paymentPlanDetailService.list(Wrappers.lambdaQuery(PaymentPlanDetail.class).in(PaymentPlanDetail::getId, idList));
        details.stream().forEach(item -> {
            item.setStatus(2);
        });
        if(!paymentPlanDetailService.saveOrUpdateBatch(details)){
            throw new DaoException("付款明细数据提交失败, 请联系管理员");
        }
    }

    /**
     * 查询供应商本月应付金额 和 判断是否超计划付款
     * @param supplierCode
     * @param companyCode
     * @return
     */
    @Override
    public BigDecimal findSupplierPaymentPlanSummary(String supplierCode,String companyCode, int action, String paymentType) {
        Calendar cl = Calendar.getInstance();
        String paymentExpireStr = DateUtils.formatYYYYMMDDDash(cl.getTime());
        PaymentPlan paymentPlan = paymentPlanService.getOne(new LambdaQueryWrapper<PaymentPlan>()
                .eq(PaymentPlan::getPaymentPlanYear, paymentExpireStr.split("-")[0])
                .eq(PaymentPlan::getPaymentPlanMonth, paymentExpireStr.split("-")[1]));
        if (Objects.nonNull(paymentPlan) && paymentPlan.getStatus() == 6) {
            PaymentPlanQuery paymentPlanQuery = new PaymentPlanQuery();
            paymentPlanQuery.setPpId(paymentPlan.getId() + "");
            paymentPlanQuery.setSupplierCode(supplierCode);
            paymentPlanQuery.setCompanyCode(companyCode);
            PaymentPlanSummary paymentPlanSummary = null;
            //如果付款计划有按 Y 代表区分预付款和对账款
            if (null != paymentPlan.getPlanType() && !paymentPlan.getPlanType().equals("Y")) {
                List<PaymentPlanSummary> paymentPlanSummaryList = paymentPlanSummaryService.findPaymentPlanSummaryBySupplier(paymentPlanQuery);
                paymentPlanSummary = new PaymentPlanSummary();
                //计算总额
                for (PaymentPlanSummary temp: paymentPlanSummaryList) {
                    paymentPlanSummary.setActualPayAmount((paymentPlanSummary.getActualPayAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getActualPayAmount()).add(
                            temp.getActualPayAmount()==null?BigDecimal.ZERO:temp.getActualPayAmount()));
                    paymentPlanSummary.setAppliedUnpaidAmount((paymentPlanSummary.getAppliedUnpaidAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getAppliedUnpaidAmount()).add(
                            temp.getAppliedUnpaidAmount()==null?BigDecimal.ZERO:temp.getAppliedUnpaidAmount()));
                    paymentPlanSummary.setAppliedPaymentAmount((paymentPlanSummary.getAppliedPaymentAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getAppliedPaymentAmount()).add(
                            temp.getAppliedPaymentAmount()==null?BigDecimal.ZERO:temp.getAppliedPaymentAmount()));
                }
            } else {
                paymentPlanQuery.setPaymentType(paymentType);
                List<PaymentPlanSummary> paymentPlanSummaryList = paymentPlanSummaryService.findPaymentPlanSummaryBySupplier(paymentPlanQuery);
                paymentPlanSummary = (null != paymentPlanSummaryList && paymentPlanSummaryList.size() > 0)?paymentPlanSummaryList.get(0):null;
            }
            //取应付金额 如果有作计划汇总
            if (Objects.nonNull(paymentPlanSummary)) {
                BigDecimal actualPayAmount = paymentPlanSummary.getActualPayAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getActualPayAmount();
                if (action == 1) {
                    return actualPayAmount.setScale(2, RoundingMode.HALF_UP);
                    //计算是否超计划
                } else if (action == 2) {
                    //本月累计请款金额 = 本月已请款金额 + 本次请款金额 + 付款计划中“已请款未付金额”；
                    BigDecimal appliedUnpaidAmount = paymentPlanSummary.getAppliedUnpaidAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getAppliedUnpaidAmount();
                    BigDecimal appliedPaymentAmount = paymentPlanSummary.getAppliedPaymentAmount()==null?BigDecimal.ZERO:paymentPlanSummary.getAppliedPaymentAmount();
                    //"③比较 供应商本月累计请款金额 与 付款计划中供应商的应付金额：
                    //如果 本月累计请款金额 大于 付款计划中供应商的应付金额，则认为供应商付款超付款计划"
                    BigDecimal diffAmount = appliedPaymentAmount.add(appliedUnpaidAmount).subtract(actualPayAmount);
                    return diffAmount.setScale(2, RoundingMode.HALF_UP);
                }
            }else if (action == 2) {
                return BigDecimal.valueOf(-1);
            }
        }
        return BigDecimal.ZERO;
    }
}
