shiyunteng
2026-08-27 b1b3da5393c75ced1afa1467be69d60af5403878
feat:合同审核、出库及履约阶段代码优化
7个文件已修改
1693 ■■■■■ 已修改文件
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractPaymentScheduleProcessService.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java 528 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java 614 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java 385 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentOffsetServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractPaymentScheduleProcessService.java
@@ -2,7 +2,9 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.by4cloud.platformx.business.dto.ContractPaymentScheduleProcessAddDTO;
import com.by4cloud.platformx.business.entity.Contract;
import com.by4cloud.platformx.business.entity.ContractPaymentScheduleProcess;
import com.by4cloud.platformx.business.entity.PaymentConfirm;
import com.by4cloud.platformx.common.core.util.R;
public interface ContractPaymentScheduleProcessService extends IService<ContractPaymentScheduleProcess> {
@@ -10,4 +12,6 @@
    R add(ContractPaymentScheduleProcessAddDTO addDTO);
    R selectScheduleProcess(Long id);
    void handleBeforeRemain(PaymentConfirm currentConfim, Contract contract);
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java
@@ -5,7 +5,6 @@
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
@@ -104,8 +103,11 @@
                        .eq(ContractSubjectMatter::getMaterialCode, contractInvoiceOutBoundVo.getSubjectMatterCode())
                        .eq(StrUtil.isNotBlank(contractInvoiceOutBoundVo.getLineNo()), ContractSubjectMatter::getLineNo, contractInvoiceOutBoundVo.getLineNo())
                        .last("limit 1"));
                if (ObjUtil.isNotNull(subjectMatter) && subjectMatter.getAdvanceNum().compareTo(new BigDecimal("0")) > 0) {
                    contractInvoiceOutBoundVo.setInvoiceNum(contractInvoiceOutBoundVo.getOutBoundNum().subtract(subjectMatter.getAdvanceNum()));
                if (ObjUtil.isNotNull(subjectMatter)) {
                    contractInvoiceOutBoundVo.setUnitPrice(subjectMatter.getUnitPrice());
                    if (subjectMatter.getAdvanceNum().compareTo(new BigDecimal("0")) > 0) {
                        contractInvoiceOutBoundVo.setInvoiceNum(contractInvoiceOutBoundVo.getOutBoundNum().subtract(subjectMatter.getAdvanceNum()));
                    }
                }
                contractInvoiceOutBoundVo.setToInvoiceNum(contractInvoiceOutBoundVo.getInvoiceNum());
            });
@@ -145,6 +147,11 @@
    public R genInvoiceInfo(GenInvoiceInfoDTO genInvoiceInfoDTO) {
        if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
            return R.failed("请选择开票出库单后再操作");
        }
        genInvoiceInfoDTO.setOutBoundInvoiceList(genInvoiceInfoDTO.getOutBoundInvoiceList().stream().filter(item->
                item.getInvoiceNum().compareTo(new BigDecimal("0"))>0).collect(Collectors.toList()));
        if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
            return R.failed("请选择开票出库单后或调整开票数量再操作");
        }
        Long contractId = null;
        //预收款开票
@@ -318,11 +325,14 @@
            if (CollUtil.isNotEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
                genInvoiceInfoDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
                    ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
                    if (!CollUtil.contains(erpCode, contractOutBound.getSubjectMatterCode())) {
                        erpCode.add(contractOutBound.getSubjectMatterCode());
                    ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                            .eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
                            .eq(StrUtil.isNotBlank(contractOutBound.getLineNo()),ContractSubjectMatter::getLineNo,contractOutBound.getLineNo())
                            .eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
                    if (!CollUtil.contains(erpCode, contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice())) {
                        erpCode.add(contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice());
                        ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
                        mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode());
                        mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice());
                        mergeVo.setMaterialInternalName(contractOutBound.getSubjectMatterName());
                        mergeVo.setQuantity(contractOutBoundInvoiceVo.getInvoiceNum());
                        Product product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
@@ -333,9 +343,6 @@
                            mergeVo.setTaxRate(new BigDecimal(product.getTaxRate()));
                            mergeVo.setTaxCode(product.getTaxCode());
                        }
                        ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                                .eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
                                .eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
                        if (ObjUtil.isNotNull(subjectMatter)) {
                            mergeVo.setUnitPrice(subjectMatter.getUnitPrice());
                            mergeVo.setUnit(subjectMatter.getUnit());
@@ -352,7 +359,7 @@
                        mergeOutBounds.add(mergeVo);
                    } else {
                        List<ContractOutBoundMergeVo> filteredList = mergeOutBounds.stream()
                                .filter(item -> contractOutBound.getSubjectMatterCode().equals(item.getMaterialCode())) // 防止空指针,建议常量在前
                                .filter(item -> item.getMaterialCode().equals(subjectMatter.getMaterialCode()+subjectMatter.getUnitPrice())) // 防止空指针,建议常量在前
                                .collect(Collectors.toList());
                        if (ArrayUtil.isNotEmpty(filteredList)) {
                            filteredList.get(0).setQuantity(filteredList.get(0).getQuantity().add(contractOutBound.getOutBoundNum()));
@@ -394,27 +401,24 @@
                            mergeVo.setSpecification(product.getProductType());
                            mergeVo.setTaxRate(new BigDecimal(product.getTaxRate()));
                            mergeVo.setTaxCode(product.getTaxCode());
                            Product productClass = productMapper.selectById(product.getParentId());
                            if (ObjUtil.isNotNull(product)) {
                                if (StrUtil.equals(product.getErpCode(), "water_bill")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*水费");
                                    mergeVo.setUnit("吨");
                                } else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*电费");
                                    mergeVo.setUnit("度");
                                } else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*房屋租赁");
                                } else {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*" + productClass.getProductName());
                                }
                            }
                        }
                        ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                                .eq(ContractSubjectMatter::getMaterialCode, schedule.getSubjectMatterCode())
                                .eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
                        if (ObjUtil.isNotNull(subjectMatter)) {
                            mergeVo.setUnitPrice(subjectMatter.getUnitPrice());
                            if (StrUtil.equals(product.getErpCode(), "water_bill")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*水费");
                                mergeVo.setUnit("吨");
                            } else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*电费");
                                mergeVo.setUnit("度");
                            } else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*房屋租赁");
                            } else {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*" + subjectMatter.getMaterialName());
                            }
                        }
                        mergeOutBounds.add(mergeVo);
                    } else {
@@ -465,7 +469,7 @@
            genInvoiceInfoDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
                ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
                if (ObjUtil.isNotNull(subjectMatter)) {
                    if (!CollUtil.contains(erpCode, subjectMatter.getMaterialCode())) {
                    if (!CollUtil.contains(erpCode, subjectMatter.getMaterialCode()+subjectMatter.getUnitPrice())) {
                        erpCode.add(subjectMatter.getMaterialCode());
                        ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
                        mergeVo.setMaterialCode(subjectMatter.getMaterialCode());
@@ -478,21 +482,20 @@
                            mergeVo.setSpecification(product.getProductType());
                            mergeVo.setTaxRate(new BigDecimal(product.getTaxRate()));
                            mergeVo.setTaxCode(product.getTaxCode());
                            Product productClass = productMapper.selectById(product.getParentId());
                            if (ObjUtil.isNotNull(product)) {
                                if (StrUtil.equals(product.getErpCode(), "water_bill")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*水费");
                                    mergeVo.setUnit("吨");
                                } else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*电费");
                                    mergeVo.setUnit("度");
                                } else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*房屋租赁");
                                } else {
                                    mergeVo.setItemName("*" + product.getTaxClass() + "*" + productClass.getProductName());
                                }
                        }
                        if (ObjUtil.isNotNull(product)) {
                            if (StrUtil.equals(product.getErpCode(), "water_bill")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*水费");
                                mergeVo.setUnit("吨");
                            } else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*电费");
                                mergeVo.setUnit("度");
                            } else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*房屋租赁");
                            } else {
                                mergeVo.setItemName("*" + product.getTaxClass() + "*" + subjectMatter.getMaterialName());
                            }
                        }
                        mergeVo.setUnitPrice(subjectMatter.getUnitPrice());
                        mergeVo.setUnit(subjectMatter.getUnit());
@@ -523,8 +526,13 @@
    @Override
    public R toInvoice(GenInvoiceInfoDTO genInvoiceInfoDTO) {
        if (ArrayUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
        if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
            return R.failed("请选择开票出库单后再操作");
        }
        genInvoiceInfoDTO.setOutBoundInvoiceList(genInvoiceInfoDTO.getOutBoundInvoiceList().stream().filter(item->
                item.getInvoiceNum().compareTo(new BigDecimal("0"))>0).collect(Collectors.toList()));
        if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
            return R.failed("请选择开票出库单后或调整开票数量再操作");
        }
        if (StrUtil.equals(genInvoiceInfoDTO.getInvoiceType(), "3") || StrUtil.equals(genInvoiceInfoDTO.getInvoiceType(), "4")) {
            if (StrUtil.isBlank(genInvoiceInfoDTO.getVehicleNo())) {
@@ -646,9 +654,7 @@
            genInvoiceInfoDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
                ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
                contractOutBound.setInvoiceStatus("1");
                if (contractOutBoundInvoiceVo.getInvoiceNum().compareTo(contractOutBound.getOutBoundNum().subtract(contractOutBound.getInvoiceNum())) <= 0) {
                    contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().add(contractOutBoundInvoiceVo.getInvoiceNum()));
                }
                contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().add(contractOutBoundInvoiceVo.getInvoiceNum()));
                contractOutBoundMapper.updateById(contractOutBound);
            });
        } else {
@@ -1220,29 +1226,30 @@
            }
            if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
                //合同状态
                if (StrUtil.equals(contract.getBillingStatus(), "2")) {
                    contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
                    if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0 &&
                            contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) == 0) {
                        contract.setBillingStatus("3");
                        contract.setContractStatus(3);
                    }
                    if (contract.getBillingAmout().compareTo(contract.getAmount()) < 0) {
                        contract.setBillingStatus("1");
                        List<ContractOutBound> outBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
                                .eq(ContractOutBound::getContractId, contract.getId())
                                .apply("invoice_num < out_bound_num"));
                        if (CollUtil.isNotEmpty(outBoundList)) {
                            contract.setBillingStatus("2");
                        }
                    }
                    //防止重复审开票审核通过后 开票金额超出合同金额
                    if (contract.getBillingAmout().compareTo(contract.getAmount()) > 0) {
                        contract.setBillingAmout(contract.getAmount());
                    }
                    contractMapper.updateById(contract);
                contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
                if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
                    contract.setBillingStatus("3");
                }
                if (contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0&&
                        contract.getBillingAmout().compareTo(contract.getAmount()) == 0){
                    contract.setContractStatus(3);
                }
                if (contract.getBillingAmout().compareTo(contract.getAmount()) < 0) {
                    contract.setBillingStatus("1");
                    List<ContractOutBound> outBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
                            .eq(ContractOutBound::getContractId, contract.getId())
                            .apply("invoice_num < out_bound_num"));
                    if (CollUtil.isNotEmpty(outBoundList)) {
                        contract.setBillingStatus("2");
                    }
                }
                //防止重复审开票审核通过后 开票金额超出合同金额
                if (contract.getBillingAmout().compareTo(contract.getAmount()) > 0) {
                    contract.setBillingAmout(contract.getAmount());
                }
                contractMapper.updateById(contract);
            } else {
                //判断 循环是否完成
                List<ContractExecDate> execDateList = contractExecDateMapper.selectList(Wrappers.<ContractExecDate>lambdaQuery().eq(ContractExecDate::getContractId, contract.getId())
@@ -1257,8 +1264,11 @@
                        contract.setBillingStatus("2");
                    }
                    contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
                    if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
                        contract.setBillingStatus("3");
                    }
                    if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0 &&
                            contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) == 0) {
                            contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0) {
                        contract.setBillingStatus("3");
                        contract.setContractStatus(3);
                    }
@@ -1352,10 +1362,8 @@
                if (ArrayUtil.isNotEmpty(outBoundInvoiceVoList)) {
                    outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
                        ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
                        if (contractOutBoundInvoiceVo.getInvoiceNum().compareTo(contractOutBound.getOutBoundNum().subtract(contractOutBound.getInvoiceNum())) <= 0) {
                            contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
                            contractOutBoundMapper.updateById(contractOutBound);
                        }
                        contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
                        contractOutBoundMapper.updateById(contractOutBound);
                    });
                }
            } else {
@@ -1437,10 +1445,8 @@
                if (ArrayUtil.isNotEmpty(outBoundInvoiceVoList)) {
                    outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
                        ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
                        if (contractOutBoundInvoiceVo.getInvoiceNum().compareTo(contractOutBound.getOutBoundNum().subtract(contractOutBound.getInvoiceNum())) <= 0) {
                            contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
                            contractOutBoundMapper.updateById(contractOutBound);
                        }
                        contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
                        contractOutBoundMapper.updateById(contractOutBound);
                    });
                }
            } else {
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java
@@ -19,6 +19,7 @@
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -44,28 +45,16 @@
        if (ObjUtil.isNull(schedule)) {
            return R.failed("履约阶段与合同不一致,请联系技术人员");
        }
        if (schedule.getStageName().equals("货到签收") && CollUtil.isEmpty(addDTO.getContractOutBoundIds())) {
            return R.failed("请选择到货的出库信息");
        }
        //合同
        Contract contract = contractMapper.selectById(schedule.getContractId());
        List<ContractSubjectMatter> subjectMatterList = subjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery().eq(ContractSubjectMatter::getContractId, contract.getId()));
        if (CollUtil.isEmpty(subjectMatterList)) {
            return R.failed("该合同标的物异常,请联系技术人员");
        if (ObjUtil.isNull(contract)) {
            return R.failed("合同信息异常");
        }
//        if (!subjectMatterList.stream().allMatch(item -> item.getDeliveryStatus() == 2)) {
//            return R.failed("出库数量小于当前合同标的物数量,无法进行当前操作");
//        }
        if (schedule.getStageName().equals("货到签收")) {
            //更新合同出库到货时间
            addDTO.getContractOutBoundIds().forEach(contractOutBoundId -> {
                ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundId);
                contractOutBound.setArrivalTime(addDTO.getProcessDate());
                contractOutBound.setArrivalAttNames(addDTO.getOutBoundAttNames());
                contractOutBound.setArrivalAttPaths(addDTO.getOutBoundAttPaths());
                contractOutBoundMapper.updateById(contractOutBound);
            });
        }
        return handleSchedule(addDTO, schedule, contract);
    }
    private void saveScheduleProcess(ContractPaymentScheduleProcessAddDTO addDTO, ContractPaymentSchedule schedule) {
        //履约
        ContractPaymentScheduleProcess contractPaymentScheduleProcess = BeanUtil.copyProperties(addDTO, ContractPaymentScheduleProcess.class);
        contractPaymentScheduleProcess.setContractId(schedule.getContractId());
@@ -77,392 +66,151 @@
        if (ObjUtil.isNull(lastProcess)) {
            baseMapper.insert(contractPaymentScheduleProcess);
        }
    }
        //更新当前阶段
        if (ObjUtil.isNull(schedule.getEffectiveDate()) && ObjUtil.isNull(schedule.getEffectiveEndDate())) {
            schedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(), schedule.getAgreedDays()));
            contractPaymentScheduleMapper.updateById(schedule);
        }
//        //查询是否有之前阶段
//        ContractPaymentSchedule beforeSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
//                .lt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder()).orderByDesc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
//        if (ObjUtil.isNotNull(beforeSchedule) && ObjUtil.isNull(beforeSchedule.getEffectiveEndDate())) {
//            beforeSchedule.setEffectiveEndDate(schedule.getEffectiveDate());
//            contractPaymentScheduleMapper.updateById(beforeSchedule);
//        }
        List<ContractOutBound> contractOutBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery().eq(ContractOutBound::getContractId, contract.getId())
                .isNotNull(ContractOutBound::getArrivalTime));
    private R handleSchedule(ContractPaymentScheduleProcessAddDTO addDTO, ContractPaymentSchedule schedule, Contract contract) {
        if (schedule.getStageName().equals("货到签收")) {
            if (CollUtil.isNotEmpty(contractOutBoundList)
                    && CollUtil.isNotEmpty(subjectMatterList)) {
                Map<String, BigDecimal> sumMap = contractOutBoundList.stream()
                        .collect(Collectors.groupingBy(
                                ContractOutBound::getSubjectMatterCode,
                                Collectors.reducing(
                                        BigDecimal.ZERO,
                                        ContractOutBound::getOutBoundNum,
                                        BigDecimal::add
                                )
                        ));
                Boolean outFlag = checkQuantityEquality(subjectMatterList, sumMap);
                //出库到货与合同标的物种类数量一致
                if (outFlag) {
                    //新增当前阶段应收
                    PaymentConfirm currentConfim = new PaymentConfirm();
                    currentConfim.setBusinessType(schedule.getStageName() + "应收");
                    currentConfim.setBusGuestId(contract.getPartyAId());
                    currentConfim.setBusGuestName(contract.getPartyA());
                    currentConfim.setContractId(contract.getId());
                    currentConfim.setContractName(contract.getContractName());
                    currentConfim.setContractNo(contract.getContractNo());
                    currentConfim.setScheduleId(schedule.getId());
                    currentConfim.setScheduleName(schedule.getStageName());
                    currentConfim.setConfirmTime(addDTO.getProcessDate());
                    currentConfim.setTransationAmount(schedule.getPlannedAmount());
                    currentConfim.setReceivableAmount(schedule.getPlannedAmount());
                    PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                    BigDecimal lastTotal = new BigDecimal("0");
                    if (ObjUtil.isNotNull(lastConfirm)) {
                        lastTotal = lastConfirm.getTotalAmount();
                    }else {
                        //客户付款完成合同
                        List<Contract> customerCompleteContractList = contractMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyAId, contract.getPartyAId())
                                .eq(Contract::getPartyBId, SecurityUtils.getUser().getCompId()).apply(" amount = paid_amount"));
                        if (CollUtil.isNotEmpty(customerCompleteContractList)){
                            List<BigDecimal> outAmountList = new ArrayList<>();
                            for (Contract completeContract:customerCompleteContractList
                            ) {
                                PaymentConfirm contractLastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,completeContract.getId())
                                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                                //查询客户付款完成合同中最后明细金额 有预收转入当前合同
                                if (contractLastConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>0&&
                                contract.getContractNo().startsWith("ZB-")){
                                    //新增完成付款合同 资金转出
                                    PaymentConfirm outConfirm = BeanUtil.copyProperties(contractLastConfirm,PaymentConfirm.class,"id","transationAmount",
                                            "advanceAmount","receivableAmount","overdueAmount","totalAmount");
                                    outConfirm.setBusinessType("资金转出");
                                    outConfirm.setConfirmTime(new Date());
                                    outConfirm.setTransationAmount(contractLastConfirm.getTotalAmount());
                                    outConfirm.setTotalAmount(new BigDecimal("0"));
                                    paymentConfirmMapper.insert(outConfirm);
                                    outAmountList.add(outConfirm.getTransationAmount());
                                }
                            }
                            if (CollUtil.isNotEmpty(outAmountList)){
                                BigDecimal currentSum = new BigDecimal("0");
                                for (BigDecimal currentAmount:outAmountList
                                ) {
                                    currentSum=currentSum.add(currentAmount);
                                    //新增当前合同 资金转入
                                    PaymentConfirm inConfirm = BeanUtil.copyProperties(lastConfirm,PaymentConfirm.class,"id","transationAmount",
                                            "advanceAmount","receivableAmount","overdueAmount","totalAmount");
                                    inConfirm.setBusinessType("资金转入");
                                    inConfirm.setConfirmTime(new Date());
                                    inConfirm.setTransationAmount(currentSum.subtract(currentAmount));
                                    inConfirm.setTotalAmount(lastConfirm.getTotalAmount().add(currentSum));
                                    if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>0){
                                        inConfirm.setAdvanceAmount(inConfirm.getTotalAmount());
                                    }else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0"))<0){
                                        inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1")));
                                    }
                                    if (contract.getContractNo().startsWith("ZB-")) {
                                        paymentConfirmMapper.insert(inConfirm);
                                    }
                                }
                            }
                        }
                    }
                    currentConfim.setTotalAmount(lastTotal.subtract(currentConfim.getReceivableAmount()));
                    if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0&&
                            contract.getContractNo().startsWith("ZB-")) {
                        paymentConfirmMapper.insert(currentConfim);
                        //更新当前阶段付款情况
                        if (lastTotal.compareTo(new BigDecimal("0"))>0){
                            if (currentConfim.getTotalAmount().compareTo(new BigDecimal("0"))>=0) {
                                schedule.setPaymentStatus(2);
                                schedule.setPlannedAmount(schedule.getPlannedAmount());
                                contractPaymentScheduleMapper.updateById(schedule);
                            }else {
                                schedule.setPaymentStatus(1);
                                schedule.setPlannedAmount(lastTotal);
                            }
                        }
                    }
                    //查询是否有后续阶段
                    List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                            .eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                            .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder()));
                    if (CollUtil.isNotEmpty(afterSchedule) && afterSchedule.size() == 1) {
                        //最后阶段生效时间
                        ContractPaymentSchedule endSchedule = afterSchedule.get(0);
                        if (StrUtil.equals(endSchedule.getStageName(), "质保金")) {
                            endSchedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(), endSchedule.getAgreedDays()));
                            contractPaymentScheduleMapper.updateById(endSchedule);
                            //当前阶段生效时间
//                            schedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(), schedule.getAgreedDays()));
//                            contractPaymentScheduleMapper.updateById(schedule);
                            //最后阶段应收
                            PaymentConfirm newConfim = new PaymentConfirm();
                            newConfim.setBusinessType(endSchedule.getStageName() + "应收");
                            newConfim.setBusGuestId(contract.getPartyAId());
                            newConfim.setBusGuestName(contract.getPartyA());
                            newConfim.setContractId(contract.getId());
                            newConfim.setContractName(contract.getContractName());
                            newConfim.setContractNo(contract.getContractNo());
                            newConfim.setScheduleId(endSchedule.getId());
                            newConfim.setScheduleName(schedule.getStageName());
                            newConfim.setConfirmTime(addDTO.getProcessDate());
                            newConfim.setTransationAmount(endSchedule.getPlannedAmount());
                            newConfim.setReceivableAmount(endSchedule.getPlannedAmount());
                            PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                            BigDecimal lastNewTotal = new BigDecimal("0");
                            if (ObjUtil.isNotNull(lastNewConfirm)) {
                                lastNewTotal = lastNewConfirm.getTotalAmount();
                            }
                            newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount()));
                            if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0&&contract.getContractNo().startsWith("ZB-")){
                                paymentConfirmMapper.insert(newConfim);
                            }
                        }
                        //更新合同下个阶段
                        contract.setNextScheduleName(endSchedule.getStageName());
                        contractMapper.updateById(contract);
                    }
                    if (CollUtil.isNotEmpty(afterSchedule) && afterSchedule.size() > 1) {
                        //更新合同下个阶段
                        contract.setNextScheduleName(afterSchedule.get(0).getStageName());
                        contractMapper.updateById(contract);
                    }
                    if (CollUtil.isEmpty(afterSchedule)) {
//                        schedule.setEffectiveEndDate(contract.getExpirationDate());
//                        contractPaymentScheduleMapper.updateById(schedule);
                        //更新合同下个阶段
                        contract.setNextScheduleName("无");
                        contractMapper.updateById(contract);
                        //当前为合同最后阶段
                        PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                                .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                        if (lastNewConfirm.getTotalAmount().compareTo(new BigDecimal("0")) >= 0
                                &&contract.getBillingAmout().compareTo(contract.getAmount())==0) {
                            //有预付且超过应收 关闭合同状态
                            contract.setContractStatus(3);
                            contractMapper.updateById(contract);
                        }
                    }
                }
            if (CollUtil.isEmpty(addDTO.getContractOutBoundIds())) {
                return R.failed("签收信息不能为空");
            }
        } else if (schedule.getStageName().equals("调试完成或验收")){
            //新增当前阶段应收
            PaymentConfirm currentConfim = new PaymentConfirm();
            currentConfim.setBusinessType(schedule.getStageName() + "应收");
            currentConfim.setBusGuestId(contract.getPartyAId());
            currentConfim.setBusGuestName(contract.getPartyA());
            currentConfim.setContractId(contract.getId());
            currentConfim.setContractName(contract.getContractName());
            currentConfim.setContractNo(contract.getContractNo());
            currentConfim.setScheduleId(schedule.getId());
            currentConfim.setScheduleName(schedule.getStageName());
            currentConfim.setConfirmTime(addDTO.getProcessDate());
            currentConfim.setTransationAmount(schedule.getPlannedAmount());
            currentConfim.setReceivableAmount(schedule.getPlannedAmount());
            PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
            BigDecimal lastTotal = new BigDecimal("0");
            if (ObjUtil.isNotNull(lastConfirm)) {
                lastTotal = lastConfirm.getTotalAmount();
            }
            currentConfim.setTotalAmount(lastTotal.subtract(currentConfim.getReceivableAmount()));
            if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0&&contract.getContractNo().startsWith("ZB-")){
                paymentConfirmMapper.insert(currentConfim);
                //更新当前阶段付款情况
                if (lastTotal.compareTo(new BigDecimal("0"))>0){
                    if (currentConfim.getTotalAmount().compareTo(new BigDecimal("0"))>=0) {
                        schedule.setPaymentStatus(2);
                        schedule.setPlannedAmount(schedule.getPlannedAmount());
                        contractPaymentScheduleMapper.updateById(schedule);
                    }else {
                        schedule.setPaymentStatus(1);
                        schedule.setPlannedAmount(lastTotal);
                    }
                }
            }
            //查询是否有后续阶段
            List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                    .eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                    .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder())
                    .gt(ContractPaymentSchedule::getPaymentRatio,"0"));
            if (CollUtil.isNotEmpty(afterSchedule) && afterSchedule.size() == 1) {
                //最后阶段生效时间
                ContractPaymentSchedule endSchedule = afterSchedule.get(0);
//                if (StrUtil.equals(endSchedule.getStageName(), "质保金")) {
//                    endSchedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(), endSchedule.getAgreedDays()));
//                    contractPaymentScheduleMapper.updateById(endSchedule);
//                    //当前阶段生效时间
//                    schedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(), schedule.getAgreedDays()));
//                    contractPaymentScheduleMapper.updateById(schedule);
//                    //最后阶段应收
//                    PaymentConfirm newConfim = new PaymentConfirm();
//                    newConfim.setBusinessType(endSchedule.getStageName() + "应收");
//                    newConfim.setBusGuestId(contract.getPartyAId());
//                    newConfim.setBusGuestName(contract.getPartyA());
//                    newConfim.setContractId(contract.getId());
//                    newConfim.setContractName(contract.getContractName());
//                    newConfim.setContractNo(contract.getContractNo());
//                    newConfim.setScheduleId(endSchedule.getId());
//                    newConfim.setScheduleName(schedule.getStageName());
//                    newConfim.setConfirmTime(addDTO.getProcessDate());
//                    newConfim.setTransationAmount(endSchedule.getPlannedAmount());
//                    newConfim.setReceivableAmount(endSchedule.getPlannedAmount());
//                    PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
//                            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
//                    BigDecimal lastNewTotal = new BigDecimal("0");
//                    if (ObjUtil.isNotNull(lastNewConfirm)) {
//                        lastNewTotal = lastNewConfirm.getTotalAmount();
//                    }
//                    newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount()));
//                    if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
//                        paymentConfirmMapper.insert(newConfim);
//                        //更新当前阶段付款情况
//                        if (lastNewTotal.compareTo(new BigDecimal("0"))>0){
//                            if (newConfim.getTotalAmount().compareTo(new BigDecimal("0"))>=0) {
//                                schedule.setPaymentStatus(2);
//                                schedule.setPlannedAmount(schedule.getPlannedAmount());
//                                contractPaymentScheduleMapper.updateById(schedule);
//                            }else {
//                                schedule.setPaymentStatus(1);
//                                schedule.setPlannedAmount(lastNewTotal);
//                            }
//                        }
//                    }
//
//                }
                //更新合同下个阶段
                contract.setNextScheduleName(endSchedule.getStageName());
                contractMapper.updateById(contract);
            }
            if (CollUtil.isNotEmpty(afterSchedule) && afterSchedule.size() > 1) {
                //更新合同下个阶段
                contract.setNextScheduleName(afterSchedule.get(0).getStageName());
                contractMapper.updateById(contract);
            }
            if (CollUtil.isEmpty(afterSchedule)) {
//                schedule.setEffectiveEndDate(contract.getExpirationDate());
//                contractPaymentScheduleMapper.updateById(schedule);
                //更新合同下个阶段
                contract.setNextScheduleName("无");
                contractMapper.updateById(contract);
                //当前为合同最后阶段
                PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                if (lastNewConfirm.getTotalAmount().compareTo(new BigDecimal("0")) >= 0
                        &&contract.getBillingAmout().compareTo(contract.getAmount())==0) {
                    //有预付且超过应收 关闭合同状态
                    contract.setContractStatus(3);
                    contractMapper.updateById(contract);
                }
            }
        }else {
            //最后阶段应收
            PaymentConfirm newConfim = new PaymentConfirm();
            newConfim.setBusinessType(schedule.getStageName() + "应收");
            newConfim.setBusGuestId(contract.getPartyAId());
            newConfim.setBusGuestName(contract.getPartyA());
            newConfim.setContractId(contract.getId());
            newConfim.setContractName(contract.getContractName());
            newConfim.setContractNo(contract.getContractNo());
            newConfim.setScheduleId(schedule.getId());
            newConfim.setScheduleName(schedule.getStageName());
            newConfim.setConfirmTime(addDTO.getProcessDate());
            newConfim.setTransationAmount(schedule.getPlannedAmount());
            newConfim.setReceivableAmount(schedule.getPlannedAmount());
            PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
            BigDecimal lastNewTotal = new BigDecimal("0");
            if (ObjUtil.isNotNull(lastNewConfirm)) {
                lastNewTotal = lastNewConfirm.getTotalAmount();
            }
            newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount()));
            if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0&&contract.getContractNo().startsWith("ZB-")) {
                paymentConfirmMapper.insert(newConfim);
                //更新当前阶段付款情况
                if (lastNewTotal.compareTo(new BigDecimal("0"))>0){
                    if (newConfim.getTotalAmount().compareTo(new BigDecimal("0"))>=0) {
                        schedule.setPaymentStatus(2);
                        schedule.setPlannedAmount(schedule.getPlannedAmount());
                    }else {
                        schedule.setPaymentStatus(1);
                        schedule.setPlannedAmount(lastNewTotal);
                    }
                    contractPaymentScheduleMapper.updateById(schedule);
                }
            }
            //更新合同下个阶段
            contract.setNextScheduleName("");
            contractMapper.updateById(contract);
            //更新合同出库到货时间
            addDTO.getContractOutBoundIds().forEach(contractOutBoundId -> {
                ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundId);
                contractOutBound.setArrivalTime(addDTO.getProcessDate());
                contractOutBound.setArrivalAttNames(addDTO.getOutBoundAttNames());
                contractOutBound.setArrivalAttPaths(addDTO.getOutBoundAttPaths());
                contractOutBoundMapper.updateById(contractOutBound);
            });
        }
        //付款比例不为0 保存收款明细
        if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
            savePaymentConfirm(addDTO, contract, schedule);
        }
        updateCurrentSchedule(addDTO.getProcessDate(), schedule, contract);
        //保存履约记录
        saveScheduleProcess(addDTO, schedule);
        return R.ok();
    }
    public boolean checkQuantityEquality(List<ContractSubjectMatter> subjectMatterList, Map<String, BigDecimal> materialCodeMap) {
        // 1. 基本校验
        if (subjectMatterList == null || materialCodeMap == null) {
            return false;
    private void savePaymentConfirm(ContractPaymentScheduleProcessAddDTO addDTO, Contract contract, ContractPaymentSchedule schedule) {
        BigDecimal amount = schedule.getPlannedAmount();
        if (schedule.getStageName().equals("货到签收")) {
            amount = new BigDecimal("0");
            //计算签收价格
            for (Long contractOutBoundId : addDTO.getContractOutBoundIds()) {
                ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundId);
                ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                        .eq(ContractSubjectMatter::getContractId, contract.getId())
                        .eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
                        .eq(ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
                        .last("limit 1"));
                amount = amount.add(contractOutBound.getOutBoundNum().multiply(subjectMatter.getUnitPrice()));
            }
            //实际到货金额按比例计算
            amount = schedule.getPlannedAmount().multiply(amount.divide(contract.getAmount(), 2, RoundingMode.HALF_UP));
        }
        // 如果要求两者包含的物料代码完全一致且数量一致,先比较 Key 的数量
        // 提取 List 中非空的 materialCode
        List<String> listCodes = subjectMatterList.stream()
                .map(ContractSubjectMatter::getMaterialCode)
                .filter(Objects::nonNull)
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        List<String> mapKeys = materialCodeMap.keySet().stream()
                .sorted()
                .collect(Collectors.toList());
        // 如果物料编码集合不一致,直接返回 false
        if (!listCodes.equals(mapKeys)) {
            return false;
        //新增当前阶段应收
        PaymentConfirm currentConfim = new PaymentConfirm();
        currentConfim.setBusinessType(schedule.getStageName() + "应收");
        currentConfim.setBusGuestId(contract.getPartyAId());
        currentConfim.setBusGuestName(contract.getPartyA());
        currentConfim.setContractId(contract.getId());
        currentConfim.setContractName(contract.getContractName());
        currentConfim.setContractNo(contract.getContractNo());
        currentConfim.setScheduleId(schedule.getId());
        currentConfim.setScheduleName(schedule.getStageName());
        currentConfim.setConfirmTime(addDTO.getProcessDate());
        currentConfim.setTransationAmount(amount);
        currentConfim.setReceivableAmount(amount);
        PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
        if (ObjUtil.isNotNull(lastConfirm)) {
            currentConfim.setTotalAmount(lastConfirm.getTotalAmount().subtract(currentConfim.getTransationAmount()));
            if (contract.getContractNo().startsWith("ZB-")) {
                paymentConfirmMapper.insert(currentConfim);
            }
            return;
        }
        currentConfim.setTotalAmount(currentConfim.getTransationAmount().multiply(new BigDecimal("-1")));
        paymentConfirmMapper.insert(currentConfim);
        handleBeforeRemain(currentConfim, contract);
    }
        // 2. 逐个比较数量
        // 假设 ContractSubjectMatter 中有 getQuantity() 方法返回 BigDecimal 或 Number
        for (ContractSubjectMatter item : subjectMatterList) {
            String code = item.getMaterialCode();
            if (code == null) continue;
            BigDecimal mapValue = materialCodeMap.get(code);
            BigDecimal listValue = item.getQuantity(); // 假设这是 List 中代表数量的字段
            // 处理 null 情况
            if (mapValue == null && listValue == null) {
                continue; // 都为空视为相等,或根据业务定为不等
    public void handleBeforeRemain(PaymentConfirm currentConfim, Contract contract) {
        //客户付款完成合同
        List<Contract> customerCompleteContractList = contractMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyAId, contract.getPartyAId())
                .eq(Contract::getPartyBId, SecurityUtils.getUser().getCompId()).eq(Contract::getContractStatus, 3));
        if (CollUtil.isNotEmpty(customerCompleteContractList)) {
            List<BigDecimal> outAmountList = new ArrayList<>();
            for (Contract completeContract : customerCompleteContractList) {
                PaymentConfirm contractLastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, completeContract.getId())
                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                //查询客户付款完成合同中最后明细金额 有预收转入当前合同
                if (contractLastConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0 &&
                        contract.getContractNo().startsWith("ZB-")) {
                    //新增完成付款合同 资金转出
                    PaymentConfirm outConfirm = BeanUtil.copyProperties(contractLastConfirm, PaymentConfirm.class, "id", "transationAmount",
                            "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                    outConfirm.setBusinessType("资金转出");
                    outConfirm.setConfirmTime(new Date());
                    outConfirm.setTransationAmount(contractLastConfirm.getTotalAmount());
                    outConfirm.setTotalAmount(new BigDecimal("0"));
                    if (contract.getContractNo().startsWith("ZB-")) {
                        paymentConfirmMapper.insert(outConfirm);
                    }
                    outAmountList.add(contractLastConfirm.getTotalAmount());
                }
            }
            if (mapValue == null || listValue == null) {
                return false; // 一个为空一个不为空,不等
            }
            // 使用 compareTo 比较 BigDecimal 值,0 表示相等
            if (listValue.compareTo(mapValue) != 0) {
                return false; // 发现不相等,立即返回
            if (CollUtil.isNotEmpty(outAmountList)) {
                BigDecimal currentSum = outAmountList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                //新增当前合同 资金转入
                PaymentConfirm inConfirm = BeanUtil.copyProperties(currentConfim, PaymentConfirm.class, "id", "transationAmount",
                        "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                inConfirm.setBusinessType("资金转入");
                inConfirm.setConfirmTime(new Date());
                inConfirm.setTransationAmount(currentSum);
                inConfirm.setTotalAmount(currentConfim.getTotalAmount().add(currentSum));
                if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                    inConfirm.setAdvanceAmount(inConfirm.getTotalAmount());
                } else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) {
                    inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1")));
                }
                if (contract.getContractNo().startsWith("ZB-")) {
                    paymentConfirmMapper.insert(inConfirm);
                }
                contract.setPaidAmount(currentSum);
                contractMapper.updateById(contract);
            }
        }
    }
        return true; // 所有匹配项数量均相等
    private void updateCurrentSchedule(Date date, ContractPaymentSchedule schedule, Contract contract) {
        //查询是否有后续阶段
        ContractPaymentSchedule afterOneSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                .eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder())
                .orderByAsc(ContractPaymentSchedule::getCreateTime)
                .last("limit 1"));
        if (ObjUtil.isNotNull(afterOneSchedule)) {
            //更新下阶段名称
            List<ContractOutBound> contractOutBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery().eq(ContractOutBound::getContractId, contract.getId())
                    .isNull(ContractOutBound::getArrivalTime));
            if (CollUtil.isEmpty(contractOutBoundList)) {
                contract.setNextScheduleName(afterOneSchedule.getStageName());
            }
        }
        if (ObjUtil.isNull(afterOneSchedule)) {
            contract.setNextScheduleName("");
        }
        contractMapper.updateById(contract);
        //更新履约阶段时间
        if (ObjUtil.isNull(schedule.getEffectiveDate()) && ObjUtil.isNull(schedule.getEffectiveEndDate())) {
            schedule.setEffectiveEndDate(DateUtil.offsetDay(date, schedule.getAgreedDays()));
        }
        contractPaymentScheduleMapper.updateById(schedule);
    }
    @Override
@@ -472,7 +220,7 @@
                        ContractPaymentSchedule::getPlannedAmount, ContractPaymentSchedule::getPlannedAmount,
                        ContractPaymentSchedule::getEffectiveEndDate, ContractPaymentSchedule::getPaymentDate,
                        ContractPaymentSchedule::getPaymentStatus, ContractPaymentSchedule::getActualAmount,
                        ContractPaymentSchedule::getAgreedDays,ContractPaymentSchedule::getPaymentRatio)
                        ContractPaymentSchedule::getAgreedDays, ContractPaymentSchedule::getPaymentRatio)
                .select(ContractPaymentScheduleProcess::getProcessDate)
                .leftJoin(ContractPaymentScheduleProcess.class, ContractPaymentScheduleProcess::getScheduleId, ContractPaymentSchedule::getId)
                .eq(ContractPaymentSchedule::getContractId, id)
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java
@@ -28,6 +28,8 @@
import com.by4cloud.platformx.business.dto.*;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.ContractPaymentScheduleProcessService;
import com.by4cloud.platformx.business.service.ContractPaymentScheduleService;
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.business.utils.BatchInsertListener;
import com.by4cloud.platformx.business.utils.ItemGeneratorUtil;
@@ -89,6 +91,7 @@
    private final StringRedisTemplate redisTemplate;
    private final ContractOutBoundMapper contractOutBoundMapper;
    private final RemoteDictService remoteDictService;
    private final ContractPaymentScheduleProcessService processService;
    @Value("${erp.ymj}")
    private String ymjErp;
@@ -136,8 +139,9 @@
            if (ObjUtil.isNotNull(bc)) {
                contract.setPartyA(bc.getCompanyName());
            }
            if (!StrUtil.equals(SecurityUtils.getUser().getCompId() + "", sgb) && StrUtil.isEmpty(bc.getErpCompanyCode())) {
                return R.failed("请完善客户ERP编码");
            if (!StrUtil.equals(SecurityUtils.getUser().getCompId() + "", sgb) && StrUtil.isEmpty(bc.getErpCompanyCode())
                    && StrUtil.isEmpty(bc.getCreditCode())) {
                return R.failed("请完善客户ERP编码或组织机构代码");
            }
        }
@@ -464,209 +468,90 @@
        Contract contract = baseMapper.selectById(id);
        contract.setContractStatus(2);
        baseMapper.updateById(contract);
        //水电房租 执行日
        List<ContractSubjectMatter> subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery()
                .eq(ContractSubjectMatter::getContractId, id));
        if (StrUtil.isNotEmpty(contract.getContractCategory()) && StrUtil.equals(contract.getContractCategory(), "water_house")) {
            if (CollUtil.isNotEmpty(subjectMatterList)) {
                for (ContractSubjectMatter contractSubjectMatter : subjectMatterList) {
                    if (StrUtil.equals(contract.getExecFrequency(), "1")) {
                        Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfWeek(contract.getEffectiveDate()),
                                DateUtil.endOfWeek(contract.getExpirationDate()), true) + 1;
                        //循环日期
                        Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfWeek(contract.getEffectiveDate()), contract.getExecDay());
                        for (int i = 0; i < weeksTrue.intValue(); i++) {
                            Date execDatei = DateUtil.offsetWeek(execDate0, i);
                            ContractExecDate execDate = new ContractExecDate();
                            execDate.setContractId(contract.getId());
                            execDate.setMatterId(contractSubjectMatter.getId());
                            execDate.setExecDate(execDatei);
                            execDate.setGenFlag("0");
                            if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                                contractExecDateMapper.insert(execDate);
                            }
                        }
                    }
                    if (StrUtil.equals(contract.getExecFrequency(), "2")) {
                        Long weeksTrue = DateUtil.betweenMonth(DateUtil.beginOfMonth(contract.getEffectiveDate()),
                                DateUtil.endOfMonth(contract.getExpirationDate()), true) + 1;
                        //循环日期
                        Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfMonth(contract.getEffectiveDate()), contract.getExecDay());
                        for (int i = 0; i < weeksTrue.intValue(); i++) {
                            Date execDatei = DateUtil.offsetMonth(execDate0, i);
                            ContractExecDate execDate = new ContractExecDate();
                            execDate.setContractId(contract.getId());
                            execDate.setMatterId(contractSubjectMatter.getId());
                            execDate.setExecDate(execDatei);
                            execDate.setGenFlag("0");
                            if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                                contractExecDateMapper.insert(execDate);
                            }
                        }
                    }
                    if (StrUtil.equals(contract.getExecFrequency(), "3")) {
                        Long weeksTrue = (DateUtil.betweenMonth(DateUtil.beginOfQuarter(contract.getEffectiveDate()),
                                DateUtil.endOfQuarter(contract.getExpirationDate()), true) + 1) / 3;
                        //循环日期
                        Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfQuarter(contract.getEffectiveDate()), contract.getExecDay());
                        for (int i = 0; i < weeksTrue.intValue(); i++) {
                            Date execDatei = DateUtil.offsetMonth(execDate0, i * 3);
                            ContractExecDate execDate = new ContractExecDate();
                            execDate.setContractId(contract.getId());
                            execDate.setMatterId(contractSubjectMatter.getId());
                            execDate.setExecDate(execDatei);
                            execDate.setGenFlag("0");
                            if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                                contractExecDateMapper.insert(execDate);
                            }
                        }
                    }
                    if (StrUtil.equals(contract.getExecFrequency(), "4")) {
                        Date startDate = contract.getEffectiveDate();
                        Date endDate = contract.getExpirationDate();
                        Integer startMonth = DateUtil.month(contract.getEffectiveDate());
                        Integer endMonth = DateUtil.month(contract.getExpirationDate());
                        if (1 <= startMonth && startMonth <= 6) {
                            startDate = DateUtil.beginOfYear(startDate);
                        }
                        if (7 <= startMonth && startMonth <= 12) {
                            startDate = DateUtil.offsetMonth(DateUtil.beginOfYear(startDate), 6);
                        }
                        if (1 <= endMonth && endMonth <= 6) {
                            endDate = DateUtil.offsetMonth(DateUtil.endOfYear(endDate), -6);
                        }
                        if (7 <= endMonth && endMonth <= 12) {
                            endDate = DateUtil.endOfYear(endDate);
                        }
                        Long weeksTrue = (DateUtil.betweenMonth(startDate, endDate, true) + 1) / 6;
                        //循环日期
                        Date execDate0 = DateUtil.offsetDay(startDate, contract.getExecDay());
                        for (int i = 0; i < weeksTrue.intValue(); i++) {
                            Date execDatei = DateUtil.offsetMonth(execDate0, i * 6);
                            ContractExecDate execDate = new ContractExecDate();
                            execDate.setContractId(contract.getId());
                            execDate.setMatterId(contractSubjectMatter.getId());
                            execDate.setExecDate(execDatei);
                            execDate.setGenFlag("0");
                            if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                                contractExecDateMapper.insert(execDate);
                            }
                        }
                    }
                    if (StrUtil.equals(contract.getExecFrequency(), "5")) {
                        Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfYear(contract.getEffectiveDate()),
                                DateUtil.endOfYear(contract.getExpirationDate()), true) + 1;
                        //循环日期
                        Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfYear(contract.getEffectiveDate()), contract.getExecDay());
                        for (int i = 0; i < weeksTrue.intValue(); i++) {
                            Date execDatei = DateUtil.offsetWeek(execDate0, i);
                            ContractExecDate execDate = new ContractExecDate();
                            execDate.setContractId(contract.getId());
                            execDate.setMatterId(contractSubjectMatter.getId());
                            execDate.setExecDate(execDatei);
                            execDate.setGenFlag("0");
                            if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                                contractExecDateMapper.insert(execDate);
                            }
                        }
                    }
                }
            }
        } else {
            ContractPaymentSchedule fitstSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId())
                    .orderByAsc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
            if (fitstSchedule.getStageName().equals("合同签订")) {
                //新增应收
                savePaymentConfirm(contract, fitstSchedule);
                //新增合同履约记录
                ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess();
                process.setContractId(contract.getId());
                process.setContractName(contract.getContractName());
                process.setScheduleId(fitstSchedule.getId());
                process.setScheduleName(fitstSchedule.getStageName());
                process.setProcessDate(contract.getSignDate());
                contractPaymentScheduleProcessMapper.insert(process);
//            //当前为合同最后阶段
//            PaymentConfirm newConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId())
//                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
//            if (ObjUtil.isNotNull(newConfirm)&&newConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>=0){
//                //有预付且超过应收 关闭合同状态
//                contract.setContractStatus(3);
//                baseMapper.updateById(contract);
//            }
            } else if (fitstSchedule.getStageName().equals("发货前")) {
                //更新合同下个阶段
                contract.setNextScheduleName("无");
                baseMapper.updateById(contract);
            } else if (fitstSchedule.getStageName().equals("货到签收")) {
                //更新合同下个阶段
                contract.setNextScheduleName("货到签收");
                baseMapper.updateById(contract);
            } else if (fitstSchedule.getStageName().equals("调试完成或验收")) {
                //更新合同下个阶段
                contract.setNextScheduleName("调试完成或验收");
                baseMapper.updateById(contract);
            } else {
                //新增应收
                savePaymentConfirm(contract, fitstSchedule);
            }
            //查询是否有后续阶段
            List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                    .eq(ContractPaymentSchedule::getContractId, fitstSchedule.getContractId())
                    .gt(ContractPaymentSchedule::getStageOrder, fitstSchedule.getStageOrder())
                    .orderByAsc(ContractPaymentSchedule::getCreateTime));
            if (ArrayUtil.isNotEmpty(afterSchedule) && afterSchedule.size() == 1) {
                //最后阶段生效时间
                ContractPaymentSchedule endSchedule = afterSchedule.get(0);
                if (StrUtil.equals(endSchedule.getStageName(), "质保金")) {
//                endSchedule.setEffectiveEndDate(DateUtil.offsetDay(new Date(),endSchedule.getAgreedDays()));
//                contractPaymentScheduleMapper.updateById(endSchedule);
                    //最后阶段应收
                    PaymentConfirm newConfim = new PaymentConfirm();
                    newConfim.setBusinessType(endSchedule.getStageName() + "应收");
                    newConfim.setBusGuestId(contract.getPartyAId());
                    newConfim.setBusGuestName(contract.getPartyA());
                    newConfim.setContractId(contract.getId());
                    newConfim.setContractName(contract.getContractName());
                    newConfim.setContractNo(contract.getContractNo());
                    newConfim.setScheduleId(endSchedule.getId());
                    newConfim.setScheduleName(endSchedule.getStageName());
                    newConfim.setConfirmTime(new Date());
                    newConfim.setTransationAmount(endSchedule.getPlannedAmount());
                    newConfim.setReceivableAmount(endSchedule.getPlannedAmount());
                    PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                    BigDecimal lastNewTotal = new BigDecimal("0");
                    if (ObjUtil.isNotNull(lastNewConfirm)) {
                        lastNewTotal = lastNewConfirm.getTotalAmount();
                    }
                    newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount()));
                    if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
                        paymentConfirmMapper.insert(newConfim);
                    }
                }
                //更新合同下个阶段
                contract.setNextScheduleName(endSchedule.getStageName());
                baseMapper.updateById(contract);
            }
            if (ArrayUtil.isNotEmpty(afterSchedule) && afterSchedule.size() > 1) {
                //第一阶段生效时间
//            fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
//            contractPaymentScheduleMapper.updateById(fitstSchedule);
                //更新合同下个阶段
                contract.setNextScheduleName(afterSchedule.get(0).getStageName());
                baseMapper.updateById(contract);
            }
            //只有当前合同签字阶段
//        if(ArrayUtil.isEmpty(afterSchedule)){
//            fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
//            contractPaymentScheduleMapper.updateById(fitstSchedule);
//        }
            handleWaterHouseCycle(contract,subjectMatterList);
            return;
        }
        //资金明细
        savePaymentConfirm(contract);
        //合同推送子公司
        pushSubCompany(contract,subjectMatterList);
        //合同中心推送
        pusnContractCenter(contract,subjectMatterList);
        contract.setNextScheduleName("发货前");
        baseMapper.updateById(contract);
    }
    private void pusnContractCenter(Contract contract,List<ContractSubjectMatter> subjectMatterList) {
        new Thread(() -> {
            try {
                JSONObject requestApply = new JSONObject();
                requestApply.put("fd_selectionmethod", "公开招标");
                requestApply.put("fd_isrelated", "是");
                requestApply.put("fd_bizId", contract.getId());
                requestApply.put("fd_remark", contract.getRemark());
                requestApply.put("fd_MainContent", "");
                requestApply.put("fd_settlementType", "00");
                requestApply.put("fd_applyType", "外销");
                requestApply.put("fd_contractsubject ", subjectMatterList.stream().map(item -> item.getMaterialName()).collect(Collectors.joining(",")));
                requestApply.put("fd_docNumber", contract.getContractNo());
                requestApply.put("fd_templateId", "19e39bb6c1edadbdb162c434274a8a18");
                requestApply.put("fd_name", contract.getContractName());
                requestApply.put("fd_signDate", DateUtil.formatDate(contract.getSignDate()));
                requestApply.put("fd_endDate", DateUtil.formatDate(contract.getExpirationDate()));
                requestApply.put("fd_contractCreater", contract.getNickName());
                requestApply.put("fd_currency", "人民币");
                requestApply.put("fd_ContractAmount", contract.getAmount());
                requestApply.put("fd_finAmount", contract.getAmount().divide(new BigDecimal("113"), 2, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("87")));
                requestApply.put("fd_docStatus", "20");
                requestApply.put("fd_taxRates", 13);
                requestApply.put("fd_customerName", contract.getPartyA());
                requestApply.put("fd_systemSource", "非煤销售系统");
                requestApply.put("fd_type", "00");
                log.info("合同中心合同起草接口入参:{}", requestApply.toJSONString());
                String respApply = HttpUtil.post("https://oatest.res.jzeg.cn/ekp/api/km-agreement/kmAgreementWebService/addSupplyContractApply", requestApply.toJSONString());
                log.info("合同中心合同起草接口回参:{}", respApply);
                JSONObject applyResp = JSONObject.parseObject(respApply);
                if (applyResp.getString("code").equals("00")) {
                    JSONObject request = new JSONObject();
                    request.put("fd_docNumber", contract.getContractNo());
                    request.put("fd_singer", contract.getNickName());
                    request.put("fd_signTime", DateUtil.formatDate(contract.getSignDate()));
                    request.put("fd_linkPerson", "");
                    request.put("fd_linkPhone", "");
                    request.put("fd_address", contract.getSignPlace());
                    request.put("fd_receivedTime", DateUtil.format(contract.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
                    request.put("fd_receivedNum", 1);
                    request.put("fd_effedate", DateUtil.formatDate(contract.getSignDate()));
                    request.put("fd_enddate", DateUtil.formatDate(contract.getExpirationDate()));
                    request.put("fd_reviewerNo", contract.getNickName());
                    request.put("fd_docStatus", "20");
                    request.put("fd_templateId", "19e39bb6c1edadbdb162c434274a8a18");
                    request.put("fd_attName", contract.getAttachmentName());
                    request.put("fd_attcontent", NetworkFileToBase64.convertNetworkFileToBase64("https://zbjt.res.jzeg.cn/api" + contract.getAttachmentUrl()));
                    log.info("合同中心同步合同接口入参:{}", request.toJSONString());
                    String resp = HttpUtil.post("https://oatest.res.jzeg.cn/ekp/api/km-agreement/kmAgreementWebService/addContractReview", request.toJSONString());
                    log.info("合同中心同步合同接口回参:{}", resp);
                    JSONObject respJson = JSONObject.parseObject(resp);
                    if (respJson.getString("code").equals("00")) {
                        contract.setCenterPushFlag("1");
                        baseMapper.updateById(contract);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
    private void pushSubCompany(Contract contract,List<ContractSubjectMatter> subjectMatterList) {
        //erp推送
        new Thread(() -> {
            try {
@@ -803,67 +688,127 @@
                e.printStackTrace();
            }
        }).start();
        //合同中心推送
        new Thread(() -> {
            try {
                JSONObject requestApply = new JSONObject();
                requestApply.put("fd_selectionmethod", "公开招标");
                requestApply.put("fd_isrelated", "是");
                requestApply.put("fd_bizId", contract.getId());
                requestApply.put("fd_remark", contract.getRemark());
                requestApply.put("fd_MainContent", "");
                requestApply.put("fd_settlementType", "00");
                requestApply.put("fd_applyType", "外销");
                requestApply.put("fd_contractsubject ", subjectMatterList.stream().map(item -> item.getMaterialName()).collect(Collectors.joining(",")));
                requestApply.put("fd_docNumber", contract.getContractNo());
                requestApply.put("fd_templateId", "19e39bb6c1edadbdb162c434274a8a18");
                requestApply.put("fd_name", contract.getContractName());
                requestApply.put("fd_signDate", DateUtil.formatDate(contract.getSignDate()));
                requestApply.put("fd_endDate", DateUtil.formatDate(contract.getExpirationDate()));
                requestApply.put("fd_contractCreater", contract.getNickName());
                requestApply.put("fd_currency", "人民币");
                requestApply.put("fd_ContractAmount", contract.getAmount());
                requestApply.put("fd_finAmount", contract.getAmount().divide(new BigDecimal("113"), 2, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("87")));
                requestApply.put("fd_docStatus", "20");
                requestApply.put("fd_taxRates", 13);
                requestApply.put("fd_customerName", contract.getPartyA());
                requestApply.put("fd_systemSource", "非煤销售系统");
                requestApply.put("fd_type", "00");
                log.info("合同中心合同起草接口入参:{}", requestApply.toJSONString());
                String respApply = HttpUtil.post("https://oatest.res.jzeg.cn/ekp/api/km-agreement/kmAgreementWebService/addSupplyContractApply", requestApply.toJSONString());
                log.info("合同中心合同起草接口回参:{}", respApply);
                JSONObject applyResp = JSONObject.parseObject(respApply);
                if (applyResp.getString("code").equals("00")) {
                    JSONObject request = new JSONObject();
                    request.put("fd_docNumber", contract.getContractNo());
                    request.put("fd_singer", contract.getNickName());
                    request.put("fd_signTime", DateUtil.formatDate(contract.getSignDate()));
                    request.put("fd_linkPerson", "");
                    request.put("fd_linkPhone", "");
                    request.put("fd_address", contract.getSignPlace());
                    request.put("fd_receivedTime", DateUtil.format(contract.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
                    request.put("fd_receivedNum", 1);
                    request.put("fd_effedate", DateUtil.formatDate(contract.getSignDate()));
                    request.put("fd_enddate", DateUtil.formatDate(contract.getExpirationDate()));
                    request.put("fd_reviewerNo", contract.getNickName());
                    request.put("fd_docStatus", "20");
                    request.put("fd_templateId", "19e39bb6c1edadbdb162c434274a8a18");
                    request.put("fd_attName", contract.getAttachmentName());
                    request.put("fd_attcontent", NetworkFileToBase64.convertNetworkFileToBase64("https://zbjt.res.jzeg.cn/api" + contract.getAttachmentUrl()));
                    log.info("合同中心同步合同接口入参:{}", request.toJSONString());
                    String resp = HttpUtil.post("https://oatest.res.jzeg.cn/ekp/api/km-agreement/kmAgreementWebService/addContractReview", request.toJSONString());
                    log.info("合同中心同步合同接口回参:{}", resp);
                    JSONObject respJson = JSONObject.parseObject(resp);
                    if (respJson.getString("code").equals("00")) {
                        contract.setCenterPushFlag("1");
                        baseMapper.updateById(contract);
    }
    private void saveScheduleProcess(Contract contract,ContractPaymentSchedule schedule) {
        //新增合同履约记录
        ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess();
        process.setContractId(contract.getId());
        process.setContractName(contract.getContractName());
        process.setScheduleId(schedule.getId());
        process.setScheduleName(schedule.getStageName());
        process.setProcessDate(contract.getSignDate());
        contractPaymentScheduleProcessMapper.insert(process);
    }
    private void handleWaterHouseCycle(Contract contract, List<ContractSubjectMatter> subjectMatterList) {
        if (CollUtil.isNotEmpty(subjectMatterList)) {
            for (ContractSubjectMatter contractSubjectMatter : subjectMatterList) {
                if (StrUtil.equals(contract.getExecFrequency(), "1")) {
                    Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfWeek(contract.getEffectiveDate()),
                            DateUtil.endOfWeek(contract.getExpirationDate()), true) + 1;
                    //循环日期
                    Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfWeek(contract.getEffectiveDate()), contract.getExecDay());
                    for (int i = 0; i < weeksTrue.intValue(); i++) {
                        Date execDatei = DateUtil.offsetWeek(execDate0, i);
                        ContractExecDate execDate = new ContractExecDate();
                        execDate.setContractId(contract.getId());
                        execDate.setMatterId(contractSubjectMatter.getId());
                        execDate.setExecDate(execDatei);
                        execDate.setGenFlag("0");
                        if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                            contractExecDateMapper.insert(execDate);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (StrUtil.equals(contract.getExecFrequency(), "2")) {
                    Long weeksTrue = DateUtil.betweenMonth(DateUtil.beginOfMonth(contract.getEffectiveDate()),
                            DateUtil.endOfMonth(contract.getExpirationDate()), true) + 1;
                    //循环日期
                    Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfMonth(contract.getEffectiveDate()), contract.getExecDay());
                    for (int i = 0; i < weeksTrue.intValue(); i++) {
                        Date execDatei = DateUtil.offsetMonth(execDate0, i);
                        ContractExecDate execDate = new ContractExecDate();
                        execDate.setContractId(contract.getId());
                        execDate.setMatterId(contractSubjectMatter.getId());
                        execDate.setExecDate(execDatei);
                        execDate.setGenFlag("0");
                        if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                            contractExecDateMapper.insert(execDate);
                        }
                    }
                }
                if (StrUtil.equals(contract.getExecFrequency(), "3")) {
                    Long weeksTrue = (DateUtil.betweenMonth(DateUtil.beginOfQuarter(contract.getEffectiveDate()),
                            DateUtil.endOfQuarter(contract.getExpirationDate()), true) + 1) / 3;
                    //循环日期
                    Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfQuarter(contract.getEffectiveDate()), contract.getExecDay());
                    for (int i = 0; i < weeksTrue.intValue(); i++) {
                        Date execDatei = DateUtil.offsetMonth(execDate0, i * 3);
                        ContractExecDate execDate = new ContractExecDate();
                        execDate.setContractId(contract.getId());
                        execDate.setMatterId(contractSubjectMatter.getId());
                        execDate.setExecDate(execDatei);
                        execDate.setGenFlag("0");
                        if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                            contractExecDateMapper.insert(execDate);
                        }
                    }
                }
                if (StrUtil.equals(contract.getExecFrequency(), "4")) {
                    Date startDate = contract.getEffectiveDate();
                    Date endDate = contract.getExpirationDate();
                    Integer startMonth = DateUtil.month(contract.getEffectiveDate());
                    Integer endMonth = DateUtil.month(contract.getExpirationDate());
                    if (1 <= startMonth && startMonth <= 6) {
                        startDate = DateUtil.beginOfYear(startDate);
                    }
                    if (7 <= startMonth && startMonth <= 12) {
                        startDate = DateUtil.offsetMonth(DateUtil.beginOfYear(startDate), 6);
                    }
                    if (1 <= endMonth && endMonth <= 6) {
                        endDate = DateUtil.offsetMonth(DateUtil.endOfYear(endDate), -6);
                    }
                    if (7 <= endMonth && endMonth <= 12) {
                        endDate = DateUtil.endOfYear(endDate);
                    }
                    Long weeksTrue = (DateUtil.betweenMonth(startDate, endDate, true) + 1) / 6;
                    //循环日期
                    Date execDate0 = DateUtil.offsetDay(startDate, contract.getExecDay());
                    for (int i = 0; i < weeksTrue.intValue(); i++) {
                        Date execDatei = DateUtil.offsetMonth(execDate0, i * 6);
                        ContractExecDate execDate = new ContractExecDate();
                        execDate.setContractId(contract.getId());
                        execDate.setMatterId(contractSubjectMatter.getId());
                        execDate.setExecDate(execDatei);
                        execDate.setGenFlag("0");
                        if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                            contractExecDateMapper.insert(execDate);
                        }
                    }
                }
                if (StrUtil.equals(contract.getExecFrequency(), "5")) {
                    Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfYear(contract.getEffectiveDate()),
                            DateUtil.endOfYear(contract.getExpirationDate()), true) + 1;
                    //循环日期
                    Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfYear(contract.getEffectiveDate()), contract.getExecDay());
                    for (int i = 0; i < weeksTrue.intValue(); i++) {
                        Date execDatei = DateUtil.offsetWeek(execDate0, i);
                        ContractExecDate execDate = new ContractExecDate();
                        execDate.setContractId(contract.getId());
                        execDate.setMatterId(contractSubjectMatter.getId());
                        execDate.setExecDate(execDatei);
                        execDate.setGenFlag("0");
                        if (DateUtil.isIn(execDatei, contract.getEffectiveDate(), contract.getExpirationDate())) {
                            contractExecDateMapper.insert(execDate);
                        }
                    }
                }
            }
        }).start();
        }
    }
    private void saveErpRequestRecord(String ymj, String toJSONString, String result) {
@@ -874,80 +819,44 @@
        erpRequestRecordMapper.insert(record);
    }
    private void savePaymentConfirm(Contract contract, ContractPaymentSchedule schedule) {
        PaymentConfirm paymentConfirm = new PaymentConfirm();
        paymentConfirm.setBusinessType(schedule.getStageName() + "应收");
        paymentConfirm.setBusGuestId(contract.getPartyAId());
        paymentConfirm.setBusGuestName(contract.getPartyA());
        paymentConfirm.setContractId(contract.getId());
        paymentConfirm.setContractName(contract.getContractName());
        paymentConfirm.setContractNo(contract.getContractNo());
        paymentConfirm.setScheduleId(schedule.getId());
        paymentConfirm.setScheduleName(schedule.getStageName());
        paymentConfirm.setConfirmTime(new Date());
        paymentConfirm.setTransationAmount(schedule.getPlannedAmount());
        paymentConfirm.setReceivableAmount(schedule.getPlannedAmount());
        paymentConfirm.setTotalAmount(schedule.getPlannedAmount().multiply(new BigDecimal("-1")));
        PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
        BigDecimal lastNewTotal = new BigDecimal("0");
        if (ObjUtil.isNotNull(lastNewConfirm)) {
            lastNewTotal = lastNewConfirm.getTotalAmount();
        }
        paymentConfirm.setTotalAmount(lastNewTotal.subtract(paymentConfirm.getReceivableAmount()));
        if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
            paymentConfirmMapper.insert(paymentConfirm);
        }
        //客户付款完成合同
        List<Contract> customerCompleteContractList = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyAId, contract.getPartyAId())
                .eq(Contract::getPartyBId, SecurityUtils.getUser().getCompId()).apply(" amount = paid_amount"));
        if (ArrayUtil.isNotEmpty(customerCompleteContractList)) {
            List<BigDecimal> outAmountList = new ArrayList<>();
            for (Contract completeContract : customerCompleteContractList
            ) {
                PaymentConfirm contractLastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, completeContract.getId())
                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                //查询客户付款完成合同中最后明细金额 有预收转入当前合同
                if (ObjUtil.isNotNull(contractLastConfirm) && contractLastConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                    //新增完成付款合同 资金转出
                    PaymentConfirm outConfirm = BeanUtil.copyProperties(contractLastConfirm, PaymentConfirm.class, "id", "transationAmount",
                            "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                    outConfirm.setBusinessType("资金转出");
                    outConfirm.setConfirmTime(new Date());
                    outConfirm.setTransationAmount(contractLastConfirm.getTotalAmount());
                    outConfirm.setTotalAmount(new BigDecimal("0"));
                    paymentConfirmMapper.insert(outConfirm);
                    outAmountList.add(outConfirm.getTransationAmount());
    private void savePaymentConfirm(Contract contract) {
        ContractPaymentSchedule fitstSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                .eq(ContractPaymentSchedule::getContractId, contract.getId())
                .eq(ContractPaymentSchedule::getStageName,"合同签订")
                .last("limit 1"));
        fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
        contractPaymentScheduleMapper.updateById(fitstSchedule);
        //报错履约记录
        saveScheduleProcess(contract,fitstSchedule);
        //保存资金明细
        if (fitstSchedule.getPaymentRatio().compareTo(new BigDecimal("0"))>0) {
            //新增应收
            PaymentConfirm currentConfim = new PaymentConfirm();
            currentConfim.setBusinessType(fitstSchedule.getStageName() + "应收");
            currentConfim.setBusGuestId(contract.getPartyAId());
            currentConfim.setBusGuestName(contract.getPartyA());
            currentConfim.setContractId(contract.getId());
            currentConfim.setContractName(contract.getContractName());
            currentConfim.setContractNo(contract.getContractNo());
            currentConfim.setScheduleId(fitstSchedule.getId());
            currentConfim.setScheduleName(fitstSchedule.getStageName());
            currentConfim.setConfirmTime(contract.getSignDate());
            currentConfim.setTransationAmount(fitstSchedule.getPlannedAmount());
            currentConfim.setReceivableAmount(fitstSchedule.getPlannedAmount());
            PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
            if (ObjUtil.isNotNull(lastConfirm)) {
                currentConfim.setTotalAmount(lastConfirm.getTotalAmount().subtract(currentConfim.getTransationAmount()));
                if (contract.getContractNo().startsWith("ZB-")) {
                    paymentConfirmMapper.insert(currentConfim);
                }
                return;
            }
            if (ArrayUtil.isNotEmpty(outAmountList)) {
                BigDecimal currentInSum = outAmountList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                //新增当前合同 资金转入
                PaymentConfirm inConfirm = BeanUtil.copyProperties(paymentConfirm, PaymentConfirm.class, "id", "transationAmount",
                        "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                inConfirm.setBusinessType("资金转入");
                inConfirm.setConfirmTime(new Date());
                inConfirm.setTransationAmount(currentInSum);
                inConfirm.setTotalAmount(paymentConfirm.getTotalAmount().add(currentInSum));
                //更新当前阶段实际收款 和 收款状态
                schedule.setActualAmount(inConfirm.getTransationAmount());
                schedule.setPaymentStatus(2);
                if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                    inConfirm.setAdvanceAmount(inConfirm.getTotalAmount());
                } else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) {
                    inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1")));
                    schedule.setActualAmount(currentInSum);
                    schedule.setPaymentStatus(1);
                }
                paymentConfirmMapper.insert(inConfirm);
                //更新当前阶段实际收款 和 收款状态
                contractPaymentScheduleMapper.updateById(schedule);
            }
        } else {
            paymentConfirmMapper.insert(paymentConfirm);
            currentConfim.setTotalAmount(currentConfim.getTransationAmount().multiply(new BigDecimal("-1")));
            paymentConfirmMapper.insert(currentConfim);
            processService.handleBeforeRemain(currentConfim,contract);
        }
    }
    @Override
@@ -2524,13 +2433,13 @@
                contract.setPartyB(SecurityUtils.getUser().getCompName());
                contract.setPartyBId(SecurityUtils.getUser().getCompId());
                contract.setContractStatus(2);
                contract.setPaidAmount(ObjUtil.isNotNull(contract.getPaidAmount())?
                        contract.getPaidAmount():new BigDecimal("0"));
                contract.setBillingAmout(ObjUtil.isNotNull(contract.getBillingAmout())?
                        contract.getBillingAmout():new BigDecimal("0"));
                contract.setPaidAmount(ObjUtil.isNotNull(contract.getPaidAmount()) ?
                        contract.getPaidAmount() : new BigDecimal("0"));
                contract.setBillingAmout(ObjUtil.isNotNull(contract.getBillingAmout()) ?
                        contract.getBillingAmout() : new BigDecimal("0"));
                contract.setBillingStatus("1");
                baseMapper.insert(contract);
                BigDecimal remainAmount = ObjUtil.isNotNull(contract.getPaidAmount())?contract.getPaidAmount():new BigDecimal("0");
                BigDecimal remainAmount = ObjUtil.isNotNull(contract.getPaidAmount()) ? contract.getPaidAmount() : new BigDecimal("0");
                List<ContractSubjectMatterExceVO> resultMatter = matterList.stream().filter(item ->
                        StrUtil.isNotBlank(item.getMaterialCode()) &&
                                StrUtil.equals(item.getContractNo(), contract.getContractNo())).collect(Collectors.toList());
@@ -2544,7 +2453,28 @@
                        subjectMatter.setRemainingQuantity(subjectMatter.getQuantity().subtract(subjectMatter.getDeliveredQuantity()));
                        subjectMatter.setDeliveryStatus(subjectMatter.getRemainingQuantity().compareTo(subjectMatter.getQuantity()) == 0 ? 0
                                : subjectMatter.getRemainingQuantity().compareTo(new BigDecimal("0")) > 0 ? 1 : 2);
                        subjectMatter.setLineNo(ItemGeneratorUtil.nextId());
                        contractSubjectMatterMapper.insert(subjectMatter);
                        if (subjectMatter.getDeliveredQuantity().compareTo(new BigDecimal("0")) > 0) {
                            //出库单
                            ContractOutBound outBound = new ContractOutBound();
                            outBound.setBusGuestId(contract.getPartyAId());
                            outBound.setBusGuestName(contract.getPartyA());
                            outBound.setContractId(contract.getId());
                            outBound.setContractName(contract.getContractName());
                            outBound.setInvoiceNum(new BigDecimal("0"));
                            outBound.setInvoiceStatus("0");
                            outBound.setOutBoundTime(new Date());
                            outBound.setOutBoundNum(subjectMatter.getDeliveredQuantity());
                            outBound.setSubjectMatterName(subjectMatter.getMaterialInternalName());
                            outBound.setSubjectMatterCode(subjectMatter.getMaterialCode());
                            contractOutBoundMapper.insert(outBound);
                            if (contract.getBillingAmout().compareTo(new BigDecimal("0")) == 0) {
                                contract.setBillingStatus("2");
                                baseMapper.updateById(contract);
                            }
                        }
                    }
                }
                List<ContractPaymentScheduleExceVO> resultSchedule = scheduleList.stream().filter(item ->
@@ -2563,20 +2493,20 @@
                                .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
                        schedule.setPaymentStatus(0);
                        schedule.setStageOrder(j + 1);
                        if (remainAmount.compareTo(new BigDecimal("0"))>0&&schedule.getPlannedAmount().compareTo(new BigDecimal("0"))>0){
                        if (remainAmount.compareTo(new BigDecimal("0")) > 0 && schedule.getPlannedAmount().compareTo(new BigDecimal("0")) > 0) {
                            remainAmount = remainAmount.subtract(schedule.getPlannedAmount());
                            if (remainAmount.compareTo(new BigDecimal("0"))>=0){
                            if (remainAmount.compareTo(new BigDecimal("0")) >= 0) {
                                schedule.setPaymentStatus(2);
                                schedule.setActualAmount(schedule.getPlannedAmount());
                            }
                            if (remainAmount.compareTo(new BigDecimal("0"))<0){
                            if (remainAmount.compareTo(new BigDecimal("0")) < 0) {
                                schedule.setPaymentStatus(1);
                                schedule.setActualAmount(schedule.getPlannedAmount().add(remainAmount));
                            }
                        }
                        contractPaymentScheduleMapper.insert(schedule);
                        if (schedule.getStageName().equals("质保金")&&contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount())?
                                contract.getPaidAmount():new BigDecimal("0")).compareTo(new BigDecimal("0"))>0){
                        if (schedule.getStageName().equals("质保金") && contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount()) ?
                                contract.getPaidAmount() : new BigDecimal("0")).compareTo(new BigDecimal("0")) > 0) {
                            PaymentConfirm confirm = new PaymentConfirm();
                            confirm.setBusGuestId(contract.getPartyAId());
                            confirm.setBusGuestName(contract.getPartyA());
@@ -2587,8 +2517,8 @@
                            confirm.setContractNo(contract.getContractNo());
                            confirm.setScheduleId(schedule.getId());
                            confirm.setScheduleName(schedule.getStageName());
                            confirm.setTransationAmount(contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount())?
                                    contract.getPaidAmount():new BigDecimal("0")));
                            confirm.setTransationAmount(contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount()) ?
                                    contract.getPaidAmount() : new BigDecimal("0")));
                            confirm.setReceivableAmount(confirm.getTransationAmount());
                            confirm.setTotalAmount(confirm.getTransationAmount().multiply(new BigDecimal("-1")));
                            paymentConfirmMapper.insert(confirm);
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java
@@ -12,6 +12,7 @@
import com.by4cloud.platformx.business.dto.OutSubjectMatterAddDTO;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.ContractPaymentScheduleProcessService;
import com.by4cloud.platformx.business.service.OutBoundService;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
@@ -46,6 +47,7 @@
    private final ContractOutBoundMapper contractOutBoundMapper;
    private final DeliveryOverdueMapper deliveryOverdueMapper;
    private final StringRedisTemplate redisTemplate;
    private final ContractPaymentScheduleProcessService processService;
    @Value("${dept.smj}")
    private String smj;
@@ -469,6 +471,162 @@
    @Override
    public R addContractOut(OutBoundAddDTO addDTO) {
        //校验参数
        R<Contract> r = vailParam(addDTO);
        if (!r.isOk()){
            return r;
        }
        Contract contract = r.getData();
        //出库
        handleOutBound(contract,addDTO);
        //保存资金明细
        BigDecimal outBoundAmount = savePaymentConfirm(contract,addDTO);
        //更新合同状态及阶段
        contract.setOutBoundAmout(outBoundAmount);
        updateContractSchedule(contract);
        return R.ok();
    }
    private void updateContractSchedule(Contract contract) {
        List<ContractSubjectMatter> unComOutList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery()
                .eq(ContractSubjectMatter::getContractId, contract.getId())
                .ne(ContractSubjectMatter::getDeliveryStatus, 2));
        if (CollUtil.isEmpty(unComOutList)){
            contract.setNextScheduleName("货到签收");
        }
        contract.setBillingStatus("2");
        contractMapper.updateById(contract);
    }
    private BigDecimal savePaymentConfirm(Contract contract,OutBoundAddDTO addDTO) {
        //查询合同是否有出库阶段
        ContractPaymentSchedule schedule = scheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId())
                .eq(ContractPaymentSchedule::getStageName, "发货前").gt(ContractPaymentSchedule::getPaymentRatio,0).last("limit 1"));
        if (ObjUtil.isNull(schedule.getEffectiveDate())&&ObjUtil.isNull(schedule.getEffectiveEndDate())){
            schedule.setEffectiveDate(addDTO.getOutBoundTime());
            schedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getOutBoundTime(),schedule.getAgreedDays()));
            scheduleMapper.updateById(schedule);
        }
        BigDecimal outAmount = new BigDecimal("0");
        //计算出库价格
        for (OutSubjectMatterAddDTO outSubjectMatterAddDTO : addDTO.getSubjectMatterList()) {
            ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                    .eq(ContractSubjectMatter::getContractId, contract.getId())
                    .eq(ContractSubjectMatter::getMaterialCode, outSubjectMatterAddDTO.getSubjectMatterCode())
                    .eq(StrUtil.isNotBlank(outSubjectMatterAddDTO.getLineNo()),ContractSubjectMatter::getLineNo, outSubjectMatterAddDTO.getLineNo())
                    .last("limit 1"));
            outAmount = outAmount.add(outSubjectMatterAddDTO.getOutBoundNum().multiply(subjectMatter.getUnitPrice()));
        }
        //存在发货前收款阶段
        if (ObjUtil.isNotNull(schedule)) {
            //新增当前阶段应收
            PaymentConfirm currentConfim = new PaymentConfirm();
            currentConfim.setBusinessType(schedule.getStageName() + "应收");
            currentConfim.setBusGuestId(contract.getPartyAId());
            currentConfim.setBusGuestName(contract.getPartyA());
            currentConfim.setContractId(contract.getId());
            currentConfim.setContractName(contract.getContractName());
            currentConfim.setContractNo(contract.getContractNo());
            currentConfim.setScheduleId(schedule.getId());
            currentConfim.setScheduleName(schedule.getStageName());
            currentConfim.setConfirmTime(addDTO.getOutBoundTime());
            //按出库比例计算应收
            currentConfim.setTransationAmount(schedule.getPlannedAmount().multiply(outAmount.divide(contract.getAmount(),2,RoundingMode.HALF_UP)));
            currentConfim.setReceivableAmount(currentConfim.getTransationAmount());
            PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
            if (ObjUtil.isNotNull(lastConfirm)) {
                currentConfim.setTotalAmount(lastConfirm.getTotalAmount().subtract(currentConfim.getTransationAmount()));
                if (contract.getContractNo().startsWith("ZB-")) {
                    paymentConfirmMapper.insert(currentConfim);
                }
                return outAmount;
            }
            currentConfim.setTotalAmount(currentConfim.getTransationAmount().multiply(new BigDecimal("-1")));
            paymentConfirmMapper.insert(currentConfim);
            //历史资金余额
            processService.handleBeforeRemain(currentConfim,contract);
        }
        return outAmount;
    }
    private void handleOutBound(Contract contract, OutBoundAddDTO addDTO) {
        addDTO.getSubjectMatterList().stream().forEach(outSubjectMatterAddDTO -> {
            ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                    .eq(ContractSubjectMatter::getContractId, contract.getId())
                    .eq(ContractSubjectMatter::getMaterialCode, outSubjectMatterAddDTO.getSubjectMatterCode())
                    .ne(ContractSubjectMatter::getDeliveryStatus, 2)
                    .eq(StrUtil.isNotEmpty(outSubjectMatterAddDTO.getLineNo()), ContractSubjectMatter::getLineNo, outSubjectMatterAddDTO.getLineNo())
                    .last("limit 1"));
            if (ObjUtil.isNull(subjectMatter)) {
                return;
            }
            subjectMatter.setLastDeliveredQuantity(outSubjectMatterAddDTO.getOutBoundNum());
            outSubjectMatterAddDTO.setUnitPrice(subjectMatter.getUnitPrice());
            if (subjectMatter.getDeliveryStatus() == 0) {
                subjectMatter.setDeliveredQuantity(outSubjectMatterAddDTO.getOutBoundNum());
                subjectMatter.setRemainingQuantity(subjectMatter.getQuantity().subtract(outSubjectMatterAddDTO.getOutBoundNum()));
            }
            if (subjectMatter.getDeliveryStatus() == 1) {
                subjectMatter.setDeliveredQuantity(subjectMatter.getDeliveredQuantity().add(outSubjectMatterAddDTO.getOutBoundNum()));
                subjectMatter.setRemainingQuantity(subjectMatter.getRemainingQuantity().subtract(outSubjectMatterAddDTO.getOutBoundNum()));
            }
            subjectMatter.setDeliveryStatus(1);
            if (subjectMatter.getRemainingQuantity().compareTo(new BigDecimal("0")) == 0) {
                subjectMatter.setDeliveryStatus(2);
            }
            subjectMatter.setActualDeliveryDate(addDTO.getOutBoundTime());
            contractSubjectMatterMapper.updateById(subjectMatter);
            //保存erp出库
            String batchNumber = genBatchNumber();
            Long outBoundId = saveErpOutBound(contract,addDTO,outSubjectMatterAddDTO,batchNumber);
            //保存合同出库记录
            saveContractOutBound(contract, addDTO, subjectMatter, outBoundId);
        });
    }
    private String genBatchNumber() {
        if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smj) || StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smjsc) ||
                StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smjzt)) {
            return generateSMJContractCKNo();
        }
        if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", sgb)) {
            return generateGYBContractCKNo();
        }
        if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", ymj)) {
            return generateYMJContractCKNo();
        }
        if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", tfgs)) {
            return generateTFContractCKNo();
        }
        if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", jxc)) {
            return generateJXCContractCKNo();
        }
        return "";
    }
    private Long saveErpOutBound(Contract contract, OutBoundAddDTO addDTO,OutSubjectMatterAddDTO outSubjectMatterAddDTO,String batchNumber) {
        OutBound outBound = new OutBound();
        outBound.setBatchNumber(batchNumber);
        outBound.setOutBoundNum(outSubjectMatterAddDTO.getOutBoundNum());
        outBound.setOutBoundAttNames(addDTO.getOutBoundAttNames());
        outBound.setOutBoundAttPaths(addDTO.getOutBoundAttPaths());
        outBound.setBusGuestName(contract.getPartyA());
        outBound.setBusGuestId(contract.getPartyAId());
        outBound.setOutBoundTime(ObjUtil.isNotNull(addDTO.getOutBoundTime()) ? addDTO.getOutBoundTime() : new Date());
        outBound.setSubjectMatterCode(outSubjectMatterAddDTO.getSubjectMatterCode());
        outBound.setSubjectMatterName(outSubjectMatterAddDTO.getSubjectMatterName());
        outBound.setOutBoundType("1");
        if (StrUtil.isEmpty(addDTO.getOutBoundType())) {
            outBound.setOutBoundType("0");
        }
        baseMapper.insert(outBound);
        return outBound.getId();
    }
    private R<Contract> vailParam(OutBoundAddDTO addDTO) {
        if (CollUtil.isEmpty(addDTO.getSubjectMatterList())) {
            return R.failed("出库标的物不能为空");
        }
@@ -523,232 +681,7 @@
                return R.failed(outSubjectMatterAddDTO.getSubjectMatterCode() + "已出库完成,不能超额出库");
            }
        }
        addDTO.getSubjectMatterList().stream().forEach(outSubjectMatterAddDTO -> {
            ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
                    .eq(ContractSubjectMatter::getContractId, contract.getId())
                    .eq(ContractSubjectMatter::getMaterialCode, outSubjectMatterAddDTO.getSubjectMatterCode())
                    .ne(ContractSubjectMatter::getDeliveryStatus, 2)
                    .eq(StrUtil.isNotEmpty(outSubjectMatterAddDTO.getLineNo()), ContractSubjectMatter::getLineNo, outSubjectMatterAddDTO.getLineNo())
                    .last("limit 1"));
            if (ObjUtil.isNull(subjectMatter)) {
                return;
            }
            subjectMatter.setLastDeliveredQuantity(outSubjectMatterAddDTO.getOutBoundNum());
            outSubjectMatterAddDTO.setUnitPrice(subjectMatter.getUnitPrice());
            if (subjectMatter.getDeliveryStatus() == 0) {
                subjectMatter.setDeliveredQuantity(outSubjectMatterAddDTO.getOutBoundNum());
                subjectMatter.setRemainingQuantity(subjectMatter.getQuantity().subtract(outSubjectMatterAddDTO.getOutBoundNum()));
            }
            if (subjectMatter.getDeliveryStatus() == 1) {
                subjectMatter.setDeliveredQuantity(subjectMatter.getDeliveredQuantity().add(outSubjectMatterAddDTO.getOutBoundNum()));
                subjectMatter.setRemainingQuantity(subjectMatter.getRemainingQuantity().subtract(outSubjectMatterAddDTO.getOutBoundNum()));
            }
            subjectMatter.setDeliveryStatus(1);
            if (subjectMatter.getRemainingQuantity().compareTo(new BigDecimal("0")) == 0) {
                subjectMatter.setDeliveryStatus(2);
            }
            subjectMatter.setActualDeliveryDate(addDTO.getOutBoundTime());
            contractSubjectMatterMapper.updateById(subjectMatter);
            //
            OutBound outBound = new OutBound();
            if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smj) || StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smjsc) ||
                    StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smjzt)) {
                outBound.setBatchNumber(generateSMJContractCKNo());
            }
            if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", sgb)) {
                outBound.setBatchNumber(generateGYBContractCKNo());
            }
            if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", ymj)) {
                outBound.setBatchNumber(generateYMJContractCKNo());
            }
            if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", tfgs)) {
                outBound.setBatchNumber(generateTFContractCKNo());
            }
            if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", jxc)) {
                outBound.setBatchNumber(generateJXCContractCKNo());
            }
            outBound.setOutBoundNum(outSubjectMatterAddDTO.getOutBoundNum());
            outBound.setOutBoundAttNames(addDTO.getOutBoundAttNames());
            outBound.setOutBoundAttPaths(addDTO.getOutBoundAttPaths());
            outBound.setBusGuestName(contract.getPartyA());
            outBound.setBusGuestId(contract.getPartyAId());
            outBound.setOutBoundTime(ObjUtil.isNotNull(addDTO.getOutBoundTime()) ? addDTO.getOutBoundTime() : new Date());
            outBound.setSubjectMatterCode(outSubjectMatterAddDTO.getSubjectMatterCode());
            outBound.setSubjectMatterName(outSubjectMatterAddDTO.getSubjectMatterName());
            outBound.setOutBoundType("1");
            if (StrUtil.isEmpty(addDTO.getOutBoundType())) {
                outBound.setOutBoundType("0");
            }
            baseMapper.insert(outBound);
            //
            saveContractOutBound(contract, addDTO, subjectMatter, outBound.getId());
        });
        //当前出库合同出库标的物
        List<ContractSubjectMatter> contractSubjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery()
                .eq(ContractSubjectMatter::getContractId, contract.getId()).ne(ContractSubjectMatter::getDeliveryStatus, 0));
        //查询合同是否有出库阶段
        ContractPaymentSchedule schedule = scheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId())
                .eq(ContractPaymentSchedule::getStageName, "发货前").gt(ContractPaymentSchedule::getPaymentRatio,0).last("limit 1"));
        //存在出库阶段
        if (ObjUtil.isNotNull(schedule)) {
            //当前出库金额
            BigDecimal outPirce = contractSubjectMatterList.stream()
                    .map(item -> (item.getDeliveryStatus() == 1 ? item.getDeliveredQuantity().multiply(item.getUnitPrice()) : item.getQuantity().multiply(item.getUnitPrice())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //出库是否完成
            if (outPirce.compareTo(contract.getBillingAmout()) > 0) {
                contract.setBillingStatus("2");
                contractMapper.updateById(contract);
            }
            if (outPirce.compareTo(contract.getBillingAmout()) == 0) {
                contract.setBillingStatus("1");
                contractMapper.updateById(contract);
            }
            if (outPirce.compareTo(contract.getAmount()) == 0 &&
                    outPirce.compareTo(contract.getBillingAmout()) == 0) {
                contract.setBillingStatus("3");
                contractMapper.updateById(contract);
            }
            //导入数据不生成应收
            if (targetContractNo.startsWith("ZB-")) {
                //计算发货前应收更新资金明细
                PaymentConfirm paymentConfirm = new PaymentConfirm();
                paymentConfirm.setBusinessType("发货前应收");
                paymentConfirm.setBusGuestId(contract.getPartyAId());
                paymentConfirm.setBusGuestName(contract.getPartyA());
                paymentConfirm.setContractId(contract.getId());
                paymentConfirm.setContractName(contract.getContractName());
                paymentConfirm.setContractNo(contract.getContractNo());
                paymentConfirm.setScheduleId(schedule.getId());
                paymentConfirm.setScheduleName(schedule.getStageName());
                paymentConfirm.setConfirmTime(addDTO.getOutBoundTime());
                //计算出库金额
                BigDecimal outAmount = addDTO.getSubjectMatterList().stream().map(item -> item.getUnitPrice().multiply(item.getOutBoundNum())).reduce(BigDecimal.ZERO, BigDecimal::add);
                paymentConfirm.setTransationAmount(outAmount.divide(new BigDecimal("100")).multiply(schedule.getPaymentRatio()));
                if (ObjUtil.isNotNull(contract.getOutBoundAmout())) {
                    contract.setOutBoundAmout(outAmount.add(contract.getOutBoundAmout()));
                } else {
                    contract.setOutBoundAmout(outAmount);
                }
                contractMapper.updateById(contract);
                //最近明细
                PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                if (ObjUtil.isNotNull(lastConfirm)) {
                    //不存在发货应收 出库总额
                    paymentConfirm.setTotalAmount(lastConfirm.getTotalAmount().subtract(paymentConfirm.getTransationAmount()));
                    if (paymentConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                        paymentConfirm.setAdvanceAmount(paymentConfirm.getTotalAmount());
                    }
                    if (paymentConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) {
                        paymentConfirm.setReceivableAmount(paymentConfirm.getTotalAmount().multiply(new BigDecimal("-1")));
                    }
                    if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
                        paymentConfirmMapper.insert(paymentConfirm);
                    }
//                }
                } else {
                    //无之前阶段应收
                    paymentConfirm.setTotalAmount(paymentConfirm.getTransationAmount().multiply(new BigDecimal("-1")));
                    if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
                        paymentConfirmMapper.insert(paymentConfirm);
                        //客户付款完成合同
                        List<Contract> customerCompleteContractList = contractMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyAId, contract.getPartyAId())
                                .eq(Contract::getPartyBId, SecurityUtils.getUser().getCompId()).apply(" amount = paid_amount"));
                        if (CollUtil.isNotEmpty(customerCompleteContractList)) {
                            List<BigDecimal> outAmountList = new ArrayList<>();
                            for (Contract completeContract : customerCompleteContractList
                            ) {
                                PaymentConfirm contractLastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, completeContract.getId())
                                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                                //查询客户付款完成合同中最后明细金额 有预收转入当前合同
                                if (contractLastConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                                    //新增完成付款合同 资金转出
                                    PaymentConfirm outConfirm = BeanUtil.copyProperties(contractLastConfirm, PaymentConfirm.class, "id", "transationAmount",
                                            "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                                    outConfirm.setBusinessType("资金转出");
                                    outConfirm.setConfirmTime(new Date());
                                    outConfirm.setTransationAmount(contractLastConfirm.getTotalAmount());
                                    outConfirm.setTotalAmount(new BigDecimal("0"));
                                    paymentConfirmMapper.insert(outConfirm);
                                    outAmountList.add(outConfirm.getTransationAmount());
                                }
                            }
                            if (CollUtil.isNotEmpty(outAmountList)) {
                                BigDecimal currentInSum = outAmountList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                                //新增当前合同 资金转入
                                PaymentConfirm inConfirm = BeanUtil.copyProperties(paymentConfirm, PaymentConfirm.class, "id", "transationAmount",
                                        "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount");
                                inConfirm.setBusinessType("资金转入");
                                inConfirm.setConfirmTime(new Date());
                                inConfirm.setTransationAmount(currentInSum);
                                inConfirm.setTotalAmount(paymentConfirm.getTotalAmount().add(currentInSum));
                                //更新当前阶段实际收款 和 收款状态
                                schedule.setActualAmount(inConfirm.getTransationAmount());
                                schedule.setPaymentStatus(2);
                                if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) {
                                    inConfirm.setAdvanceAmount(inConfirm.getTotalAmount());
                                } else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) {
                                    inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1")));
                                    schedule.setActualAmount(paymentConfirm.getTotalAmount().subtract(currentInSum));
                                    schedule.setPaymentStatus(1);
                                }
                                paymentConfirmMapper.insert(inConfirm);
                                //更新当前阶段实际收款 和 收款状态
                                scheduleMapper.updateById(schedule);
                            }
                        }
                    }
                }
            }
            //更新发货前收款生效时间
            if (ObjUtil.isNull(schedule.getEffectiveDate())) {
                //更新履约
                ContractPaymentScheduleProcess contractPaymentScheduleProcess = new ContractPaymentScheduleProcess();
                contractPaymentScheduleProcess.setContractId(schedule.getContractId());
                contractPaymentScheduleProcess.setContractName(schedule.getContractName());
                contractPaymentScheduleProcess.setScheduleId(schedule.getId());
                contractPaymentScheduleProcess.setScheduleName(schedule.getStageName());
                contractPaymentScheduleProcess.setProcessDate(addDTO.getOutBoundTime());
                ContractPaymentScheduleProcess lastProcess = scheduleProcessMapper.selectOne(Wrappers.<ContractPaymentScheduleProcess>lambdaQuery().eq(ContractPaymentScheduleProcess::getContractId, schedule.getContractId())
                        .eq(ContractPaymentScheduleProcess::getScheduleId, schedule.getId()).last("limit 1"));
                if (ObjUtil.isNull(lastProcess)) {
                    scheduleProcessMapper.insert(contractPaymentScheduleProcess);
                }
            }
            //查询是否有后续阶段
            List<ContractPaymentSchedule> afterSchedule = scheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                    .eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                    .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder())
                    .orderByAsc(ContractPaymentSchedule::getCreateTime));
            if (CollUtil.isNotEmpty(afterSchedule) && contract.getOutBoundAmout().compareTo(contract.getAmount()) == 0) {
                contract.setNextScheduleName(afterSchedule.get(0).getStageName());
                contractMapper.updateById(contract);
            }
            if (CollUtil.isEmpty(afterSchedule)) {
                schedule.setEffectiveEndDate(contract.getExpirationDate());
                scheduleMapper.updateById(schedule);
                //更新合同下个阶段
                contract.setNextScheduleName("无");
                contractMapper.updateById(contract);
                //当前为合同最后阶段
                PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                        .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                if (lastNewConfirm.getTotalAmount().compareTo(new BigDecimal("0")) >= 0
                        && contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
                    //有预付且超过应收 关闭合同状态
                    contract.setContractStatus(3);
                    contractMapper.updateById(contract);
                }
            }
        }
        return R.ok();
        return R.ok(contract);
    }
    /**
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -209,7 +209,7 @@
                }
                paid = paid.add(addDTO.getTransationAmount());
                contract.setPaidAmount(paid);
                if (paid.compareTo(contract.getAmount().subtract(contract.getDropAmount())) == 0&&contract.getBillingAmout().compareTo(contract.getAmount())==0) {
                if (paid.compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0&&contract.getBillingAmout().compareTo(contract.getAmount())==0) {
                    contract.setContractStatus(3);
                    contract.setPaidAmount(contract.getAmount().subtract(contract.getDropAmount()));
                }
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentOffsetServiceImpl.java
@@ -137,7 +137,7 @@
        }
        paid = paid.add(paymentOffset.getOffsetAmount());
        contract.setPaidAmount(paid);
        if (paid.compareTo(contract.getAmount().subtract(contract.getDropAmount()))==0&&contract.getBillingAmout().compareTo(contract.getAmount())==0){
        if (paid.compareTo(contract.getAmount().subtract(contract.getDropAmount()))>=0&&contract.getBillingAmout().compareTo(contract.getAmount())==0){
//            contract.setBillingStatus("2");
            contract.setContractStatus(3);
        }