feat:faet:出库加批次号,合同履约加销方购方履约,到货单据必填校验,验收单据必填校验,单位新增法人、委托代理人字段 、合同出库新增erp出库ID
16个文件已修改
9个文件已添加
1505 ■■■■ 已修改文件
platformx-boot/src/main/resources/application-dev.yml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/BipRequestRecord.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/Contract.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractOutBound.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/OutBound.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/PaymentConfirm.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/PaymentSlip.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractSubjectMatterVo.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/pom.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractSubjectMatterController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/BipRequestRecordMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/PaymentSlipMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractSubjectMatterService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java 267 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractSubjectMatterServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java 784 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/utils/SignHelper.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/mapper/BipRequestRecordMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/mapper/ContractOutBoundMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/mapper/PaymentSlipMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/template/ymjjgclht.doc 补丁 | 查看 | 原始文档 | blame | 历史
platformx-boot/src/main/resources/application-dev.yml
@@ -41,3 +41,11 @@
#bip 配置
bip:
  url:
  codes: 111111111111111111111111,222222222222222222
  appKey:
  appSecret:
# 文件上传配置
file:
  local:
    base-path: D:\\Users\\platformx\\Downloads\\img
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/BipRequestRecord.java
New file
@@ -0,0 +1,35 @@
package com.by4cloud.platformx.business.entity;
import com.by4cloud.platformx.common.data.mybatis.BaseModel;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import lombok.Data;
import org.hibernate.annotations.Table;
/**
 * 时间
 * syt
 */
@Data
@Entity//加了才能自动生成表
@Table(appliesTo="bip_request_record",comment = "bip请求记录")//给表加注释
@jakarta.persistence.Table(name = "bip_request_record")//数据库创建的表明
public class BipRequestRecord  extends BaseModel<BipRequestRecord> {
    @Schema(description = "接口名称")
    @Column(columnDefinition="VARCHAR(128) comment '接口名称'")
    private String interfaceName;
    @Schema(description = "入参")
    @Column(columnDefinition="text comment '入参'")
    private String requestParams;
    @Schema(description = "回参")
    @Column(columnDefinition="text comment '回参'")
    private String responseParams;
    @Schema(description = "结果码")
    @Column(columnDefinition="VARCHAR(32) comment '结果码'")
    private String responseCode;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/Contract.java
@@ -78,14 +78,18 @@
    @Column(columnDefinition = "tinyint(2) default 0 comment '合同服务属性'")
    private Integer contractAttribute;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Schema(description = "签署日期")
    @Column(columnDefinition = "date comment '签署日期'")
    private Date signDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
    @Schema(description = "签订地点")
    @Column(columnDefinition = "VARCHAR(255) comment '签订地点'")
    private String signPlace;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Schema(description = "生效日期")
    @Column(columnDefinition = "date comment '生效日期'")
    private Date effectiveDate;
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractOutBound.java
@@ -75,4 +75,8 @@
    @Column(columnDefinition="text comment '到货单据路径'")
    private String arrivalAttPaths;
    @Schema(description = "erp出库ID")
    @Column(columnDefinition="bigint comment 'erp出库ID'")
    private Long outBoundId;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/OutBound.java
@@ -24,6 +24,10 @@
@jakarta.persistence.Table(name = "out_bound")//数据库创建的表明
public class OutBound extends BaseModel<OutBound> {
    @Schema(description = "出库批次号")
    @Column(columnDefinition="VARCHAR(64) comment '出库批次号'")
    private String batchNumber;
    @Schema(description = "客商名称")
    @Column(columnDefinition="VARCHAR(64) comment '客商名称'")
    private String busGuestName;
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/PaymentConfirm.java
@@ -75,4 +75,24 @@
    @Schema(description = "阶段名称")
    @Column(columnDefinition = "VARCHAR(64) comment '阶段名称'")
    private String scheduleName;
    @Schema(description = "是否为BIP同步")
    @Column(columnDefinition="tinyint DEFAULT  '0' COMMENT  '是否为BIP同步'")
    private Integer isBip;
    @Schema(description = "bip收款单id ")
    @Column(columnDefinition="VARCHAR(64) comment 'bip收款单id'")
    private String bipId;
    /**
     *  付款方式 0/现汇 1/承兑 数据字典
     */
    @Schema(description = "付款方式 ")
    @Column(columnDefinition="int(1) comment '付款方式'")
    private Integer payType;
    @Schema(description = "收款单编号")
    @Column(columnDefinition="VARCHAR(64) comment '收款单编号'")
    private String paymentCode;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/PaymentSlip.java
New file
@@ -0,0 +1,47 @@
package com.by4cloud.platformx.business.entity;
import com.by4cloud.platformx.common.data.mybatis.BaseModel;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import lombok.Data;
import org.hibernate.annotations.Table;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 2026年5月22日 08:41:53
 * syt
 */
@Data
@Entity//加了才能自动生成表
@Table(appliesTo="payment_slip",comment = "收款单")//给表加注释
@jakarta.persistence.Table(name = "payment_slip")//数据库创建的表明
public class PaymentSlip extends BaseModel<PaymentSlip> {
    @Schema(description = "客商名称")
    @Column(columnDefinition="VARCHAR(64) comment '客商名称'")
    private String busGuestName;
    @Schema(description = "客商ID")
    @Column(columnDefinition="bigint comment '客商ID'")
    private Long busGuestId;
    @Schema(description = "收款日期")
    @Column(columnDefinition="datetime comment '收款日期'")
    private Date paymentTime;
    @Schema(description = "收款金额")
    @Column(columnDefinition="decimal(10,2) comment '收款金额  /元 两位小数'")
    private BigDecimal paymentAmount;
    @Schema(description = "收款单编号")
    @Column(columnDefinition="VARCHAR(255) comment '收款单编号'")
    private String paymentNumber;
    @Schema(description = "付款方式 ")
    @Column(columnDefinition="VARCHAR(64) comment '付款方式'")
    private String payType;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractSubjectMatterVo.java
New file
@@ -0,0 +1,24 @@
package com.by4cloud.platformx.business.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ContractSubjectMatterVo {
    private String materialName;
    @Schema(description = "标的物编码(内部唯一编码)")
    private String materialCode;
    @Schema(description = "标的物编码(内部唯一名称)")
    private String materialInternalName;
    @Schema(description = "数量")
    private BigDecimal quantity;
    @Schema(description = "已交付数量")
    private BigDecimal deliveredQuantity;
}
platformx-business-finance-biz/pom.xml
@@ -135,10 +135,17 @@
            <groupId>com.by4cloud</groupId>
            <artifactId>platformx-common-datasource</artifactId>
        </dependency>
        <!--easypoi-->
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.2</version> <!-- 请使用最新稳定版 -->
        </dependency>
    </dependencies>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
@@ -169,6 +176,17 @@
                            <skip>false</skip>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-resources-plugin</artifactId>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <nonFilteredFileExtensions>
                                <nonFilteredFileExtension>docx</nonFilteredFileExtension>
                                <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
                            </nonFilteredFileExtensions>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractController.java
@@ -15,6 +15,7 @@
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.common.security.annotation.Inner;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import com.by4cloud.platformx.common.excel.annotation.ResponseExcel;
@@ -174,4 +175,14 @@
                .gt(Contract::getBillingAmout,new BigDecimal("0"))));
    }
    /**
     * 根据模版生成word一煤机加工承揽合同
     * @param id id
     * @return R
     */
    @Operation(summary = "根据模版生成word合同" , description = "根据模版生成word合同" )
    @GetMapping("/exportContractYMJJGCLWord/{id}" )
    public void exportContractYMJJGCLWord(@PathVariable("id" ) Long id, HttpServletResponse response) {
        contractService.exportContractYMJJGCLWord(id,response);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractSubjectMatterController.java
@@ -116,4 +116,14 @@
    public List<ContractSubjectMatter> export(ContractSubjectMatter contractSubjectMatter,Long[] ids) {
        return contractSubjectMatterService.list(Wrappers.lambdaQuery(contractSubjectMatter).in(ArrayUtil.isNotEmpty(ids), ContractSubjectMatter::getId, ids));
    }
    /**
     * 通过合同id查询标的物履约进度
     * @param id id
     * @return R
     */
    @GetMapping("/selectSubjectMatterProcess/{id}" )
    public R selectSubjectMatterProcess(@PathVariable("id" ) Long id) {
        return contractSubjectMatterService.selectSubjectMatterProcess(id);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/BipRequestRecordMapper.java
New file
@@ -0,0 +1,11 @@
package com.by4cloud.platformx.business.mapper;
import com.by4cloud.platformx.business.entity.BipRequestRecord;
import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BipRequestRecordMapper extends PlatformxBaseMapper<BipRequestRecord> {
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/PaymentSlipMapper.java
New file
@@ -0,0 +1,12 @@
package com.by4cloud.platformx.business.mapper;
import com.by4cloud.platformx.business.entity.PaymentSlip;
import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PaymentSlipMapper extends PlatformxBaseMapper<PaymentSlip> {
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractService.java
@@ -7,6 +7,7 @@
import com.by4cloud.platformx.business.vo.ContractDetailVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.data.mybatis.IIService;
import jakarta.servlet.http.HttpServletResponse;
/**
 * @author 28254
@@ -28,4 +29,11 @@
    void takeEffect(Long id);
    R copyNewContract(Long id);
    /**
     * 一煤机加工承揽合同
     * @param id
     * @param response
     */
    void exportContractYMJJGCLWord(Long id,HttpServletResponse response);
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractSubjectMatterService.java
@@ -2,7 +2,9 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.by4cloud.platformx.business.entity.ContractSubjectMatter;
import com.by4cloud.platformx.common.core.util.R;
public interface ContractSubjectMatterService extends IService<ContractSubjectMatter> {
    R selectSubjectMatterProcess(Long id);
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java
@@ -14,15 +14,13 @@
import com.by4cloud.platformx.business.vo.ContractPaymentScheduleVo;
import com.by4cloud.platformx.business.vo.ScheduleProcessVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -130,6 +128,50 @@
                    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 (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 (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 (ArrayUtil.isNotEmpty(outAmountList.toArray())){
                                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")));
                                    }
                                    paymentConfirmMapper.insert(inConfirm);
                                }
                            }
                        }
                    }
                    currentConfim.setTotalAmount(lastTotal.subtract(currentConfim.getReceivableAmount()));
                    if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) {
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java
@@ -1,12 +1,16 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.admin.api.entity.SysDept;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.business.api.feign.RemoteFlowProcessService;
import com.by4cloud.platformx.business.constant.FlowNameEnum;
import com.by4cloud.platformx.business.dto.ContractAddDTO;
@@ -18,17 +22,23 @@
import com.by4cloud.platformx.business.vo.ContractDetailVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import com.by4cloud.platformx.flow.task.api.feign.RemoteBusinessService;
import com.by4cloud.platformx.flow.task.dto.ProcessInstanceParamDto;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
 * @author cd
@@ -44,7 +54,13 @@
    private final ContractPaymentScheduleProcessMapper contractPaymentScheduleProcessMapper;
    private final PaymentConfirmMapper paymentConfirmMapper;
    private final CurrentOverdueMapper currentOverdueMapper;
    private final BusinessCustomerMapper businessCustomerMapper;
    private final RemoteFlowProcessService remoteFlowProcessService;
    private final ContractTemplateMapper contractTemplateMapper;
    private final RemoteDeptService remoteDeptService;
    @Value("${file.local.base-path}")
    private String basePath;
    @Override
    public R add(ContractAddDTO addDTO) {
@@ -208,29 +224,8 @@
                .orderByAsc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
        if (fitstSchedule.getStageName().equals("合同签订")){
            //新增应收
            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(fitstSchedule.getId());
            paymentConfirm.setScheduleName(fitstSchedule.getStageName());
            paymentConfirm.setConfirmTime(new Date());
            paymentConfirm.setTransationAmount(fitstSchedule.getPlannedAmount());
            paymentConfirm.setReceivableAmount(fitstSchedule.getPlannedAmount());
            paymentConfirm.setTotalAmount(fitstSchedule.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 (fitstSchedule.getPaymentRatio().compareTo(new BigDecimal("0"))>0){
                paymentConfirmMapper.insert(paymentConfirm);
            }
            savePaymentConfirm(contract,fitstSchedule);
            //新增合同履约记录
            ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess();
            process.setContractId(contract.getId());
@@ -239,14 +234,14 @@
            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);
            }
//            //当前为合同最后阶段
//            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("无");
@@ -261,29 +256,7 @@
            baseMapper.updateById(contract);
        }else {
            //新增应收
            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(fitstSchedule.getId());
            paymentConfirm.setScheduleName(fitstSchedule.getStageName());
            paymentConfirm.setConfirmTime(new Date());
            paymentConfirm.setTransationAmount(fitstSchedule.getPlannedAmount());
            paymentConfirm.setReceivableAmount(fitstSchedule.getPlannedAmount());
            paymentConfirm.setTotalAmount(fitstSchedule.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 (fitstSchedule.getPaymentRatio().compareTo(new BigDecimal("0"))>0) {
                paymentConfirmMapper.insert(paymentConfirm);
            }
            savePaymentConfirm(contract,fitstSchedule);
        }
        //查询是否有后续阶段
        List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
@@ -343,6 +316,76 @@
            fitstSchedule.setEffectiveDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
            fitstSchedule.setEffectiveEndDate(contract.getExpirationDate());
            contractPaymentScheduleMapper.updateById(fitstSchedule);
        }
    }
    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 (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 (ArrayUtil.isNotEmpty(outAmountList.toArray())){
                BigDecimal currentSum = new BigDecimal("0");
                for (BigDecimal currentAmount:outAmountList
                     ) {
                    currentSum=currentSum.add(currentAmount);
                    //新增当前合同 资金转入
                    PaymentConfirm inConfirm = BeanUtil.copyProperties(paymentConfirm,PaymentConfirm.class,"id","transationAmount",
                            "advanceAmount","receivableAmount","overdueAmount","totalAmount");
                    inConfirm.setBusinessType("资金转入");
                    inConfirm.setConfirmTime(new Date());
                    inConfirm.setTransationAmount(currentSum.subtract(currentAmount));
                    inConfirm.setTotalAmount(paymentConfirm.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")));
                    }
                    paymentConfirmMapper.insert(inConfirm);
                }
            }
        }
    }
@@ -426,6 +469,7 @@
        newContract.setPaidAmount(new BigDecimal("0"));
        newContract.setBillingStatus("0");
        newContract.setErpPushFlag("0");
        newContract.setContractStatus(0);
        List<Contract> contracts;
        contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,newContract.getContractNo()));
        while (ArrayUtil.isNotEmpty(contracts.toArray())){
@@ -433,6 +477,111 @@
            contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,newContract.getContractNo()));
        }
        baseMapper.insert(newContract);
        List<ContractSubjectMatter> subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery().eq(ContractSubjectMatter::getContractId,id));
        subjectMatterList.stream().forEach(contractSubjectMatter -> {
            ContractSubjectMatter subjectMatter = BeanUtil.copyProperties(contractSubjectMatter,ContractSubjectMatter.class,"id","createTime");
            subjectMatter.setContractId(newContract.getId());
            subjectMatter.setDeliveryStatus(0);
            subjectMatter.setDeliveredQuantity(new BigDecimal("0"));
            subjectMatter.setRemainingQuantity(new BigDecimal("0"));
            contractSubjectMatterMapper.insert(subjectMatter);
        });
        List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId,id));
        scheduleList.stream().forEach(contractPaymentSchedule -> {
            ContractPaymentSchedule schedule = BeanUtil.copyProperties(contractPaymentSchedule,ContractPaymentSchedule.class,"id","createTime");
            schedule.setContractId(newContract.getId());
            schedule.setPaymentStatus(0);
            schedule.setActualAmount(new BigDecimal("0"));
            schedule.setEffectiveDate(null);
            schedule.setEffectiveEndDate(null);
            contractPaymentScheduleMapper.insert(schedule);
        });
        return R.ok();
    }
    @Override
    public void exportContractYMJJGCLWord(Long id, HttpServletResponse response) {
        Contract contract = baseMapper.selectById(id);
        List<ContractSubjectMatter> subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery()
                .eq(ContractSubjectMatter::getContractId,id).orderByAsc(ContractSubjectMatter::getCreateTime));
        Map<String,Object> map = new HashMap<>();
        //合同基本信息
        map.put("partyA",contract.getPartyA());
        map.put("partyB",contract.getPartyB());
        map.put("contractNo",contract.getContractNo());
        map.put("signPlace",contract.getSignPlace());
        map.put("signDate",DateUtil.formatDate(contract.getSignDate()));
        map.put("signDateYMD",DateUtil.format(contract.getSignDate(), DatePattern.CHINESE_DATE_PATTERN));
        map.put("total", contract.getAmount());
        map.put("amountWords", Convert.digitToChinese(contract.getAmount()));
        //标的物
        List<Map<String,Object>> items = new ArrayList<>();
        List<RowRenderData> dataList = new ArrayList<>();
        AtomicReference<Integer> no = new AtomicReference<>(0);
        subjectMatterList.stream().forEach(contractSubjectMatter -> {
            Map<String,Object> item = new HashMap<>();
            item.put("no",no);
            item.put("materialName",contractSubjectMatter.getMaterialName());
            item.put("guige","");
            item.put("unit","");
            item.put("quantity",contractSubjectMatter.getQuantity());
            item.put("danzhong","");
            item.put("zongzhong","");
            item.put("unitPrice",contractSubjectMatter.getUnitPrice());
            item.put("price",contractSubjectMatter.getTotalAmount());
            items.add(item);
            no.updateAndGet(v -> v + 1);
        });
        map.put("items",items);
        //定制方
        BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId());
        map.put("companyName",customer.getCompanyName());
        map.put("legalPerson",customer.getLegalPerson());
        map.put("contactPhone",customer.getContactPhone());
        map.put("bankName",customer.getBankName());
        map.put("bankAccount",customer.getBankAccount());
        //承揽方
        R<SysDept> r = remoteDeptService.getById(contract.getPartyBId());
        SysDept dept = r.getData();
        map.put("companyName",dept.getOrgName());
        map.put("legalPerson1",StrUtil.isNotEmpty(dept.getLegalPerson())?dept.getLegalPerson():"");
        map.put("entrustedAgent",StrUtil.isNotEmpty(dept.getLegalPerson())?"":dept.getEntrustedAgent());
        map.put("orgContact",dept.getOrgContact());
        map.put("orgBank",dept.getOrgBank());
        map.put("orgBankAccount",dept.getOrgBankAccount());
        //生成文件名
        Long time = new Date().getTime();
        // 生成的word格式
        String formatSuffix = ".docx";
        // 拼接后的文件名
        String fileName = time + formatSuffix;//文件名  带后缀
        //导出word
        try {
            // 1. 加载模版
            // 假设模版在 resources/templates/template.docx
            ClassPathResource resource = new ClassPathResource("template/ymjjgclht.docx");
            // 配置列表策略
            Configure config = Configure.builder()
                    .bind("items", new LoopRowTableRenderPolicy()) // 将 items 绑定到行循环策略
                    .build();
            // 2. 编译并渲染数据
            XWPFTemplate xwpfTemplate = XWPFTemplate.compile(resource.getInputStream(),config).render(map);
            // 3. 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".docx");
            // 4. 写入输出流
            OutputStream out = response.getOutputStream();
            xwpfTemplate.write(out);
            out.flush();
            out.close();
            xwpfTemplate.close(); // 重要:关闭模版释放资源
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractSubjectMatterServiceImpl.java
@@ -4,7 +4,14 @@
import com.by4cloud.platformx.business.entity.ContractSubjectMatter;
import com.by4cloud.platformx.business.mapper.ContractSubjectMatterMapper;
import com.by4cloud.platformx.business.service.ContractSubjectMatterService;
import com.by4cloud.platformx.business.vo.ContractSubjectMatterVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.data.mybatis.BaseModel;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * 合同标的物明细表
 *
@@ -13,4 +20,13 @@
 */
@Service
public class ContractSubjectMatterServiceImpl extends ServiceImpl<ContractSubjectMatterMapper, ContractSubjectMatter> implements ContractSubjectMatterService {
    @Override
    public R selectSubjectMatterProcess(Long id) {
        MPJLambdaWrapper<ContractSubjectMatter> wrapper = new MPJLambdaWrapper<ContractSubjectMatter>()
                .selectAll(ContractSubjectMatter.class)
                .eq(ContractSubjectMatter::getContractId,id)
                .orderByAsc(ContractSubjectMatter::getCreateTime);
        List<ContractSubjectMatterVo> matterVoList = baseMapper.selectJoinList(ContractSubjectMatterVo.class,wrapper);
        return R.ok(matterVoList);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java
@@ -1,6 +1,7 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil;
@@ -13,6 +14,7 @@
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.OutBoundService;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -73,8 +75,16 @@
        }
        //当前入库标的物
        Map<Long, Object> currentOutMap = new HashMap<>();
        //出库批次
        String batchNumber = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
        //出库
        addDTO.getSubjectMatterList().stream().forEach(outSubjectMatterAddDTO -> {
            OutBound outBound = BeanUtil.copyProperties(outSubjectMatterAddDTO, OutBound.class);
            outBound.setBatchNumber(batchNumber);
            outBound.setBusGuestName(addDTO.getBusGuestName());
            outBound.setBusGuestId(addDTO.getBusGuestId());
            outBound.setOutBoundTime(addDTO.getOutBoundTime());
            baseMapper.insert(outBound);
            BigDecimal remainNum = outSubjectMatterAddDTO.getOutBoundNum();
            for (ContractSubjectMatter subjectMatter : subjectMatterList) {
                if (outSubjectMatterAddDTO.getSubjectMatterCode().equals(subjectMatter.getMaterialCode())) {
@@ -92,7 +102,7 @@
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            saveContractOutBound(contract, addDTO, subjectMatter,outBound.getId());
                        } else {
                            BigDecimal currentOut = remainNum.add(subjectMatter.getRemainingQuantity());
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
@@ -103,7 +113,7 @@
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            saveContractOutBound(contract, addDTO, subjectMatter,outBound.getId());
                            break;
                        }
@@ -119,7 +129,7 @@
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            saveContractOutBound(contract, addDTO, subjectMatter,outBound.getId());
                        } else {
                            BigDecimal currentOut = remainNum.add(subjectMatter.getQuantity());
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
@@ -130,17 +140,13 @@
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            saveContractOutBound(contract, addDTO, subjectMatter,outBound.getId());
                            break;
                        }
                    }
                }
            }
            OutBound outBound = BeanUtil.copyProperties(outSubjectMatterAddDTO, OutBound.class);
            outBound.setBusGuestName(addDTO.getBusGuestName());
            outBound.setBusGuestId(addDTO.getBusGuestId());
            outBound.setOutBoundTime(addDTO.getOutBoundTime());
            baseMapper.insert(outBound);
        });
        //出库应收款明细
@@ -215,6 +221,49 @@
                        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 (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 (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 (ArrayUtil.isNotEmpty(outAmountList.toArray())){
                                    BigDecimal currentSum = new BigDecimal("0");
                                    for (BigDecimal currentAmount:outAmountList
                                    ) {
                                        currentSum=currentSum.add(currentAmount);
                                        //新增当前合同 资金转入
                                        PaymentConfirm inConfirm = BeanUtil.copyProperties(paymentConfirm,PaymentConfirm.class,"id","transationAmount",
                                                "advanceAmount","receivableAmount","overdueAmount","totalAmount");
                                        inConfirm.setBusinessType("资金转入");
                                        inConfirm.setConfirmTime(new Date());
                                        inConfirm.setTransationAmount(currentSum.subtract(currentAmount));
                                        inConfirm.setTotalAmount(paymentConfirm.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")));
                                        }
                                        paymentConfirmMapper.insert(inConfirm);
                                    }
                                }
                            }
                        }
                    }
@@ -316,7 +365,7 @@
        return R.ok();
    }
    private void saveContractOutBound(Contract contract, OutBoundAddDTO addDTO, ContractSubjectMatter subjectMatter) {
    private void saveContractOutBound(Contract contract, OutBoundAddDTO addDTO, ContractSubjectMatter subjectMatter,Long outBoundId) {
        ContractOutBound contractOutBound = new ContractOutBound();
        contractOutBound.setContractId(contract.getId());
        contractOutBound.setContractName(contract.getContractName());
@@ -328,6 +377,7 @@
        contractOutBound.setOutBoundNum(subjectMatter.getLastDeliveredQuantity());
        contractOutBound.setOutBoundAttNames(addDTO.getOutBoundAttNames());
        contractOutBound.setOutBoundAttPaths(addDTO.getOutBoundAttPaths());
        contractOutBound.setOutBoundId(outBoundId);
        contractOutBoundMapper.insert(contractOutBound);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -1,32 +1,39 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.admin.api.entity.SysDept;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.business.dto.PaymentConfirmAddDTO;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.ContractPaymentScheduleMapper;
import com.by4cloud.platformx.business.mapper.CurrentOverdueMapper;
import com.by4cloud.platformx.business.mapper.HistoryOverdueMapper;
import com.by4cloud.platformx.business.mapper.PaymentConfirmMapper;
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.BusinessCustomerService;
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.business.service.PaymentConfirmService;
import com.by4cloud.platformx.business.utils.SignHelper;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * 收款确认
@@ -34,6 +41,7 @@
 * @author syt
 * @date 2026-04-29 11:33:26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentConfirmServiceImpl extends ServiceImpl<PaymentConfirmMapper, PaymentConfirm> implements PaymentConfirmService {
@@ -43,109 +51,608 @@
    private final ContractPaymentScheduleMapper contractPaymentScheduleMapper;
    private final CurrentOverdueMapper currentOverdueMapper;
    private final HistoryOverdueMapper historyOverdueMapper;
    private final PaymentSlipMapper paymentSlipMapper;
    private final BipRequestRecordMapper bipRequestRecordMapper;
    private final RemoteDeptService remoteDeptService;
    private final RedisTemplate redisTemplate;
    @Value("${bip.url}")
    private String url;
    @Value("${bip.codes}")
    private String codes;
    @Value("${bip.appKey}")
    private String appKey;
    @Value("${bip.appSecret}")
    private String appSecret;
    @Override
    public R add(PaymentConfirmAddDTO addDTO) {
        Contract contract = contractService.getOne(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,addDTO.getContractNo()));
        if(ObjUtil.isNull(contract)){
            return R.failed("合同查询失败,请检查合同编号");
        if (StrUtil.isNotBlank(addDTO.getContractNo())) {
            Contract contract = contractService.getOne(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo, addDTO.getContractNo()));
            BusinessCustomer customer = businessCustomerService.getOne(Wrappers.<BusinessCustomer>lambdaQuery()
                    .eq(StrUtil.isNotBlank(addDTO.getBusGuestName()), BusinessCustomer::getCompanyName, addDTO.getBusGuestName())
                    .eq(StrUtil.isNotBlank(addDTO.getBusGuestId()), BusinessCustomer::getId, addDTO.getBusGuestId()));
            if (ObjUtil.isNull(customer)) {
                return R.failed("客商查询失败,请检查客商");
            }
            PaymentConfirm lastConfirm = baseMapper.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();
            }
            //转入
            if (StrUtil.equals(addDTO.getInOrOut(), "1")) {
                BigDecimal newtotal = addDTO.getTransationAmount().add(lastTotal);
                PaymentConfirm entity = new PaymentConfirm();
                entity.setContractId(contract.getId());
                entity.setContractName(contract.getContractName());
                entity.setContractNo(addDTO.getContractNo());
                if (ObjUtil.isNotNull(lastConfirm)) {
                    entity.setScheduleId(lastConfirm.getScheduleId());
                    entity.setScheduleName(lastConfirm.getScheduleName());
                }
                entity.setBusGuestId(customer.getId());
                entity.setBusGuestName(customer.getCompanyName());
                entity.setBusinessType("客户付款");
                if (newtotal.compareTo(new BigDecimal("0")) > 0) {
                    entity.setTransationAmount(addDTO.getTransationAmount());
                    entity.setAdvanceAmount(newtotal);
                    entity.setTotalAmount(newtotal);
                    entity.setConfirmTime(new Date());
                    baseMapper.insert(entity);
                } else if (newtotal.compareTo(new BigDecimal("0")) == 0) {
                    entity.setTransationAmount(addDTO.getTransationAmount());
                    entity.setTotalAmount(newtotal);
                    entity.setConfirmTime(new Date());
                    baseMapper.insert(entity);
                } else {
                    entity.setTransationAmount(addDTO.getTransationAmount());
                    entity.setReceivableAmount(newtotal.multiply(new BigDecimal("-1")));
                    entity.setTotalAmount(newtotal);
                    entity.setConfirmTime(new Date());
                    baseMapper.insert(entity);
                }
                //更新付款阶段付款
                List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                        .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 2)
                        .orderByAsc(ContractPaymentSchedule::getCreateTime));
                if (ArrayUtil.isNotEmpty(scheduleList.toArray())) {
                    BigDecimal remain = addDTO.getTransationAmount();
                    for (ContractPaymentSchedule schedule : scheduleList) {
                        BigDecimal lastRemain = remain;
                        remain = remain.subtract(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount() :
                                schedule.getPlannedAmount().subtract(schedule.getActualAmount()));
                        if (remain.compareTo(new BigDecimal("0")) >= 0) {
                            schedule.setActualAmount(schedule.getPlannedAmount());
                            schedule.setPaymentDate(addDTO.getConfirmTime());
                            schedule.setPaymentStatus(2);
                            contractPaymentScheduleMapper.updateById(schedule);
                            //查询是否有当前逾期
                            CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                    .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                            if (ObjUtil.isNotNull(currentOverdue)) {
                                //新增逾期历史
                                HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                                historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                                historyOverdue.setCompId(schedule.getCompId());
                                historyOverdueMapper.insert(historyOverdue);
                                //删除当前逾期
                                currentOverdueMapper.deleteById(currentOverdue);
                            }
                        } else {
                            schedule.setActualAmount(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount().add(remain) :
                                    schedule.getActualAmount().add(lastRemain));
                            schedule.setPaymentDate(addDTO.getConfirmTime());
                            schedule.setPaymentStatus(1);
                            contractPaymentScheduleMapper.updateById(schedule);
                            //查询是否有当前逾期
                            CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                    .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                            if (ObjUtil.isNotNull(currentOverdue)) {
                                //新增逾期历史
                                HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                                historyOverdue.setReceivableAmount(lastRemain);
                                historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                                historyOverdue.setCompId(schedule.getCompId());
                                historyOverdueMapper.insert(historyOverdue);
                                //查询历史已付逾期金额
                                List<HistoryOverdue> historyOverdueList = historyOverdueMapper.selectList(Wrappers.<HistoryOverdue>lambdaQuery().eq(HistoryOverdue::getScheduleId, currentOverdue.getScheduleId()));
                                BigDecimal hisTotal = historyOverdueList.stream().map(item -> item.getReceivableAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                                //更新当前逾期
                                currentOverdue.setReceivableAmount(schedule.getPlannedAmount().subtract(hisTotal));
                                currentOverdueMapper.updateById(currentOverdue);
                            }
                            break;
                        }
                    }
                }
                //更新合同已付款
                BigDecimal paid = new BigDecimal("0");
                if (ObjUtil.isNotNull(contract.getPaidAmount())) {
                    paid = contract.getPaidAmount();
                }
                paid = paid.add(addDTO.getTransationAmount());
                contract.setPaidAmount(paid);
                if (paid.compareTo(contract.getAmount()) > 0) {
                    contract.setPaidAmount(contract.getAmount());
                }
                contractService.updateById(contract);
            }
            //转出
            if (StrUtil.equals(addDTO.getInOrOut(), "2")) {
                PaymentConfirm entity = new PaymentConfirm();
                entity.setContractId(contract.getId());
                entity.setContractName(contract.getContractName());
                entity.setContractNo(addDTO.getContractNo());
                entity.setBusGuestId(customer.getId());
                entity.setBusGuestName(customer.getCompanyName());
                entity.setBusinessType("");
                entity.setTransationAmount(addDTO.getTransationAmount());
                BigDecimal newtotal = addDTO.getTransationAmount().multiply(new BigDecimal("-1")).add(lastConfirm.getTotalAmount());
                if (newtotal.compareTo(new BigDecimal("0")) > 0) {
                    entity.setAdvanceAmount(newtotal);
                    entity.setTotalAmount(newtotal);
                } else if (newtotal.compareTo(new BigDecimal("0")) == 0) {
                    entity.setTotalAmount(newtotal);
                } else {
                    return R.failed("当前客户余额为" + lastConfirm.getTotalAmount() + "不足以满足当前发生金额,无法操作");
                }
                entity.setConfirmTime(new Date());
                baseMapper.insert(entity);
            }
            // 查询所有付款阶段是否都付款完成
            List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId()));
            if (ArrayUtil.isNotEmpty(scheduleList.toArray())) {
                if (scheduleList.stream().allMatch(item -> Objects.equals(item.getPaymentStatus(), 2))) {
                    contract.setContractStatus(3);
                    contractService.updateById(contract);
                }
                ;
            }
        }else {
            List<Contract> customerContractList = contractService.list(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyAId, addDTO.getBusGuestId())
                    .eq(Contract::getPartyBId,SecurityUtils.getUser().getCompId()).orderByAsc(Contract::getCreateTime).apply(" amount != paid_amount"));
            if (ArrayUtil.isEmpty(customerContractList.toArray())) {
                return R.failed("为查询到未付款合同");
            }
            BusinessCustomer customer = businessCustomerService.getOne(Wrappers.<BusinessCustomer>lambdaQuery()
                    .eq(StrUtil.isNotBlank(addDTO.getBusGuestName()), BusinessCustomer::getCompanyName, addDTO.getBusGuestName())
                    .eq(ObjUtil.isNotNull(addDTO.getBusGuestId()), BusinessCustomer::getId, addDTO.getBusGuestId())
                    .last("limit 1"));
            if (ObjUtil.isNull(customer)) {
                return  R.failed("客商查询失败");
            }
            BigDecimal transtionAmount = addDTO.getTransationAmount();
            //剩余付款
            BigDecimal transtionRemainAmount = transtionAmount;
            //收到付款的合同
            List<Contract> payContractList = new ArrayList<>();
            //付款完成的合同
            List<Contract> payCompleteContractList = new ArrayList<>();
            //付款未完成的合同
            List<Contract> payNoCompleteContractList = new ArrayList<>();
            //有预付款的合同
            List<Contract> advanceContractList = new ArrayList<>();
            //付款时间
            Date payDate = addDTO.getConfirmTime();
            for (Contract contract : customerContractList) {
                PaymentConfirm lastConfirm = baseMapper.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();
                }
                //合同最近明细总额为0 或 > 0 情况下
                if (lastTotal.compareTo(new BigDecimal("0")) >= 0) {
                    log.info("当前合同号:{},明细总额无应收款", contract.getContractNo());
                    advanceContractList.add(contract);
                    continue;
                }
                transtionRemainAmount = transtionRemainAmount.add(lastTotal);
                PaymentConfirm entity = new PaymentConfirm();
                entity.setContractId(contract.getId());
                entity.setContractName(contract.getContractName());
                entity.setContractNo(contract.getContractNo());
                if (ObjUtil.isNotNull(lastConfirm)) {
                    entity.setScheduleId(lastConfirm.getScheduleId());
                    entity.setScheduleName(lastConfirm.getScheduleName());
                }
                entity.setBusGuestId(customer.getId());
                entity.setBusGuestName(customer.getCompanyName());
                entity.setBusinessType("客户付款");
                if (transtionRemainAmount.compareTo(new BigDecimal("0")) > 0) {
                    entity.setTransationAmount(lastTotal.multiply(new BigDecimal("-1")));
                    entity.setTotalAmount(new BigDecimal("0"));
                    entity.setConfirmTime(payDate);
                    baseMapper.insert(entity);
                    payContractList.add(contract);
                } else if (transtionRemainAmount.compareTo(new BigDecimal("0")) == 0) {
                    entity.setTransationAmount(lastTotal.multiply(new BigDecimal("-1")));
                    entity.setTotalAmount(new BigDecimal("0"));
                    entity.setConfirmTime(payDate);
                    baseMapper.insert(entity);
                    payContractList.add(contract);
                    break;
                } else {
                    entity.setTransationAmount(transtionRemainAmount.subtract(lastTotal));
                    entity.setTotalAmount(transtionAmount);
                    entity.setConfirmTime(payDate);
                    baseMapper.insert(entity);
                    payContractList.add(contract);
                    break;
                }
            }
            payContractList.stream().forEach(contract -> {
                //更新付款阶段付款
                List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                        .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 2)
                        .orderByAsc(ContractPaymentSchedule::getCreateTime));
                if (ArrayUtil.isNotEmpty(scheduleList.toArray())) {
                    BigDecimal remain = transtionAmount;
                    for (ContractPaymentSchedule schedule : scheduleList) {
                        BigDecimal lastRemain = remain;
                        remain = lastRemain.subtract(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount() :
                                schedule.getPlannedAmount().subtract(schedule.getActualAmount()));
                        if (remain.compareTo(new BigDecimal("0")) >= 0) {
                            schedule.setActualAmount(schedule.getPlannedAmount());
                            schedule.setPaymentDate(payDate);
                            schedule.setPaymentStatus(2);
                            contractPaymentScheduleMapper.updateById(schedule);
                            //查询是否有当前逾期
                            CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                    .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                            if (ObjUtil.isNotNull(currentOverdue)) {
                                //新增逾期历史
                                HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                                historyOverdue.setPaymentTime(payDate);
                                historyOverdue.setCompId(schedule.getCompId());
                                historyOverdueMapper.insert(historyOverdue);
                                //删除当前逾期
                                currentOverdueMapper.deleteById(currentOverdue);
                            }
                        } else {
                            schedule.setActualAmount(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount().add(remain) :
                                    schedule.getActualAmount().add(lastRemain));
                            schedule.setPaymentDate(payDate);
                            schedule.setPaymentStatus(1);
                            contractPaymentScheduleMapper.updateById(schedule);
                            //查询是否有当前逾期
                            CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                    .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                            if (ObjUtil.isNotNull(currentOverdue)) {
                                //新增逾期历史
                                HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                                historyOverdue.setReceivableAmount(lastRemain);
                                historyOverdue.setPaymentTime(payDate);
                                historyOverdue.setCompId(schedule.getCompId());
                                historyOverdueMapper.insert(historyOverdue);
                                //查询历史已付逾期金额
                                List<HistoryOverdue> historyOverdueList = historyOverdueMapper.selectList(Wrappers.<HistoryOverdue>lambdaQuery().eq(HistoryOverdue::getScheduleId, currentOverdue.getScheduleId()));
                                BigDecimal hisTotal = historyOverdueList.stream().map(item -> item.getReceivableAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                                //更新当前逾期
                                currentOverdue.setReceivableAmount(schedule.getPlannedAmount().subtract(hisTotal));
                                currentOverdueMapper.updateById(currentOverdue);
                            }
                            break;
                        }
                    }
                }
                //合同所有付款阶段
                List<ContractPaymentSchedule> payComScheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                        .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 0)
                        );
                if (ArrayUtil.isNotEmpty(payComScheduleList.toArray())){
                    BigDecimal payTotal = payComScheduleList.stream().map(item->StrUtil.equals(item.getPaymentStatus() + "", "0") ? item.getPlannedAmount() :
                            item.getActualAmount()).reduce(BigDecimal.ZERO,BigDecimal::add);
                    contract.setPaidAmount(payTotal);
                    if (payComScheduleList.stream().allMatch(item -> Objects.equals(item.getPaymentStatus(), 2))) {
                        contract.setContractStatus(3);
                    }
                    contractService.updateById(contract);
                    if (contract.getAmount().compareTo(contract.getPaidAmount()) == 0) {
                        payCompleteContractList.add(contract);
                    }
                    //付款 且 付款未全付
                    if (contract.getAmount().compareTo(contract.getPaidAmount()) > 0) {
                        payNoCompleteContractList.add(contract);
                    }
                }
            });
            //客户预付有剩余 且 有预付款的合同
            if (transtionRemainAmount.compareTo(new BigDecimal("0")) > 0) {
                if (ArrayUtil.isNotEmpty(payNoCompleteContractList.toArray())){
                    //余额 放到付款未完成合同 预收
                    Contract lastContract = payNoCompleteContractList.get(0);
                    //保存明细
                    saveNewPaymentConfirm(customer,null,lastContract,transtionRemainAmount,payDate);
                }
                if (ArrayUtil.isEmpty(payNoCompleteContractList.toArray())&&ArrayUtil.isNotEmpty(advanceContractList.toArray())){
                    //客户预付有剩余 没有预付款的合同
                    Contract lastContract = advanceContractList.get(0);
                    //保存明细
                    saveNewPaymentConfirm(customer,null,lastContract,transtionRemainAmount,payDate);
                }
                if (ArrayUtil.isEmpty(payNoCompleteContractList.toArray())&&ArrayUtil.isEmpty(advanceContractList.toArray())
                        &&ArrayUtil.isNotEmpty(payCompleteContractList.toArray())) {
                    //客户预付有剩余 没有预付款的合同
                    Contract lastContract = payCompleteContractList.get(payCompleteContractList.size() - 1);
                    //保存明细
                    saveNewPaymentConfirm(customer,null,lastContract,transtionRemainAmount,payDate);
                }
            }
        }
        return R.ok();
    }
    @Override
    public R syncPaymentRecepit() {
        String accessToken = "";
        if (redisTemplate.hasKey("BIP_TOKEN")) {
            accessToken = (String) redisTemplate.opsForValue().get("BIP_TOKEN");
        } else {
            getAccessToken(accessToken);
        }
        if (StrUtil.isEmpty(accessToken)) {
            return R.failed("获取token失败");
        }
        String[] bipCodeArr = codes.split(",");
        for (String bipCode : bipCodeArr) {
            //入参
            JSONObject params = genParams(bipCode);
            String finalAccessToken = accessToken;
            new Thread(() -> {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                log.info("SK_CX Request:", params.toJSONString());
                String result = HttpUtil.post(url + "/yonbip/EFI/collection/list?access_token=" + finalAccessToken, params.toJSONString());
                log.info("SK_CX Response:{}", result);
                //保存请求记录
                saveBipRequestRecord(params, result);
                JSONObject resultJson = JSONObject.parseObject(result);
                if (resultJson.containsKey("code") && resultJson.getString("code").equals("200")) {
                    handleAndSave(bipCode, resultJson);
                }
            }).start();
        }
        return R.ok();
    }
    private JSONObject genParams(String bipCode){
        JSONObject params = new JSONObject();
        params.put("pageIndex", 1);
        params.put("pageSize", 999);
        params.put("open_billDate_begin", DateUtil.offsetDay(new Date(), -1) + " 00:00:00");
        params.put("open_billDate_begin", DateUtil.today() + " 00:00:00");
        //单据状态已审批
        params.put("verifyState", new String[]{"2"});
        //往来对象客户
        params.put("objectType", new String[]{"1"});
        //单位
        JSONObject simpleMap = new JSONObject();
        simpleMap.put("financeOrg.code", bipCode);
        params.put("simple", simpleMap);
        return params;
    }
    private void getAccessToken(String accessToken) {
        long timestamp = System.currentTimeMillis();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("appKey", appKey);
        paramMap.put("timestamp", timestamp);
        String signature = null;
        try {
            signature = SignHelper.sign(paramMap, appSecret);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }
        String getTokenResult = HttpUtil.get(url + "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken?appKey=" + appKey + "&timestamp=" + timestamp
                + "&signature=" + signature);
        log.info("Get access_token Response:", getTokenResult);
        JSONObject tokenJson = JSONObject.parseObject(getTokenResult);
        if (!tokenJson.containsKey("code") || !tokenJson.getString("code").equals("200")) {
            log.error("Get access_token ERROR");
            return;
        }
        if (ObjUtil.isNull(tokenJson.get("data")) || ObjUtil.isNull(JSONObject.parseObject(tokenJson.getString("data")))) {
            log.error("access_token value exception");
            return;
        }
        accessToken = JSONObject.parseObject(tokenJson.getString("data")).getString("access_token");
        log.info("access_token value:", accessToken);
        redisTemplate.opsForValue().set("BIP_TOKEN", accessToken, tokenJson.getIntValue("expire") - 10, TimeUnit.SECONDS);
    }
    private void saveBipRequestRecord(JSONObject params, String result) {
        BipRequestRecord record = new BipRequestRecord();
        record.setInterfaceName("<XSJZ_SK_CX_001>-收款单查询接口");
        record.setRequestParams(params.toJSONString());
        record.setResponseParams(result);
        record.setResponseCode(JSONObject.parseObject(result).getString("code"));
        bipRequestRecordMapper.insert(record);
    }
    private void handleAndSave(String bipCode, JSONObject resultJson) {
        R<SysDept> r = remoteDeptService.selectDeptByBipCode(bipCode);
        if (!r.isOk()) {
            log.error("bipcode查询单位失败");
            return;
        }
        SysDept dept = r.getData();
        JSONObject dataJson = JSONObject.parseObject(resultJson.getString("data"));
        if (ObjUtil.isNull(dataJson)) {
            log.error("返回结果中data解析失败");
            return;
        }
        JSONArray recordList = JSONArray.parseArray(resultJson.getString("recordList"));
        if (ArrayUtil.isEmpty(recordList.toArray())) {
            log.error("返回结果中recordList为空");
            return;
        }
        log.info("==================开始处理收款单信息===================");
        recordList.stream().forEach(record -> {
            savePaymentConfirm((JSONObject) record, dept);
        });
        log.info("==================结束处理收款单信息===================");
    }
    private void savePaymentConfirm(JSONObject record, SysDept dept) {
        List<Contract> contractList = contractService.list(Wrappers.<Contract>lambdaQuery().eq(Contract::getPartyA, record.getString("bodyItemCustomerName"))
                .eq(Contract::getPartyBId, dept.getDeptId()).orderByAsc(Contract::getCreateTime));
        if (ArrayUtil.isEmpty(contractList.toArray())) {
            log.error("付款单id:{},甲方:{},乙方:{},无相关合同", record.getString("id"), record.getString("bodyItemCustomerName"), dept.getName());
            return;
        }
        BusinessCustomer customer = businessCustomerService.getOne(Wrappers.<BusinessCustomer>lambdaQuery()
                .eq(StrUtil.isNotBlank(addDTO.getBusGuestName()),BusinessCustomer::getCompanyName,addDTO.getBusGuestName())
                .eq(StrUtil.isNotBlank(addDTO.getBusGuestId()),BusinessCustomer::getId,addDTO.getBusGuestId()));
        if(ObjUtil.isNull(customer)){
            return R.failed("客商查询失败,请检查客商");
                .eq(StrUtil.isNotBlank(record.getString("bodyItemCustomerName")), BusinessCustomer::getCompanyName, record.getString("bodyItemCustomerName"))
        );
        if (ObjUtil.isNull(customer)) {
            log.error("付款单id:{},客商查询失败,请检查客商", record.getString("id"));
            return;
        }
        PaymentConfirm lastConfirm = baseMapper.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();
        if (ObjUtil.isNull(record.getBigDecimal("bodyItemOriTaxExcludedAmount"))) {
            log.error("付款单id:{},付款单无税金额,异常", record.getString("id"));
            return;
        }
        //保存付款单
        Boolean codeFlag = savePaymentSlip(customer,record);
        if (codeFlag){
            log.error("付款单id:{},付款单已存在");
            return;
        }
        BigDecimal transtionAmount = record.getBigDecimal("bodyItemOriTaxExcludedAmount");
        //剩余付款
        BigDecimal transtionRemainAmount = transtionAmount;
        //收到付款的合同
        List<Contract> payContractList = new ArrayList<>();
        //付款完成的合同
        List<Contract> payCompleteContractList = new ArrayList<>();
        //付款未完成的合同
        List<Contract> payNoCompleteContractList = new ArrayList<>();
        //有预付款的合同
        List<Contract> advanceContractList = new ArrayList<>();
        //付款时间
        Date payDate = DateUtil.parse(record.getString("billDate"), DatePattern.NORM_DATETIME_FORMAT);
        for (Contract contract : contractList) {
            PaymentConfirm lastConfirm = baseMapper.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();
            }
        //转入
        if (StrUtil.equals(addDTO.getInOrOut(),"1")){
            BigDecimal newtotal = addDTO.getTransationAmount().add(lastTotal);
            //合同最近明细总额为0 或 > 0 情况下
            if (lastTotal.compareTo(new BigDecimal("0")) >= 0) {
                log.info("当前合同号:{},明细总额无应收款", contract.getContractNo());
                advanceContractList.add(contract);
                continue;
            }
            transtionRemainAmount = transtionRemainAmount.add(lastTotal);
            PaymentConfirm entity = new PaymentConfirm();
            entity.setContractId(contract.getId());
            entity.setContractName(contract.getContractName());
            entity.setContractNo(addDTO.getContractNo());
            if(ObjUtil.isNotNull(lastConfirm)){
            entity.setContractNo(contract.getContractNo());
            if (ObjUtil.isNotNull(lastConfirm)) {
                entity.setScheduleId(lastConfirm.getScheduleId());
                entity.setScheduleName(lastConfirm.getScheduleName());
            }
            entity.setBusGuestId(customer.getId());
            entity.setBusGuestName(customer.getCompanyName());
            entity.setBusinessType("客户付款");
            if (newtotal.compareTo(new BigDecimal("0"))>0){
                entity.setTransationAmount(addDTO.getTransationAmount());
                entity.setAdvanceAmount(newtotal);
                entity.setTotalAmount(newtotal);
                entity.setConfirmTime(new Date());
            entity.setIsBip(1);
            entity.setPaymentCode(record.getString("code"));
            entity.setPayType(record.get("bodyItemSettleModeName") != null ? record.getString("bodyItemSettleModeName").contains("承兑汇票") ? 1 : 0 : null);
            entity.setBipId(record.getString("id"));
            if (transtionRemainAmount.compareTo(new BigDecimal("0")) > 0) {
                entity.setTransationAmount(lastTotal.multiply(new BigDecimal("-1")));
                entity.setTotalAmount(new BigDecimal("0"));
                entity.setConfirmTime(payDate);
                baseMapper.insert(entity);
            }else if (newtotal.compareTo(new BigDecimal("0"))==0){
                entity.setTransationAmount(addDTO.getTransationAmount());
                entity.setTotalAmount(newtotal);
                entity.setConfirmTime(new Date());
            } else if (transtionRemainAmount.compareTo(new BigDecimal("0")) == 0) {
                entity.setTransationAmount(lastTotal.multiply(new BigDecimal("-1")));
                entity.setTotalAmount(new BigDecimal("0"));
                entity.setConfirmTime(payDate);
                baseMapper.insert(entity);
            }else {
                entity.setTransationAmount(addDTO.getTransationAmount());
                entity.setReceivableAmount(newtotal.multiply(new BigDecimal("-1")));
                entity.setTotalAmount(newtotal);
                entity.setConfirmTime(new Date());
                break;
            } else {
                entity.setTransationAmount(transtionRemainAmount.subtract(lastTotal));
                entity.setTotalAmount(transtionAmount);
                entity.setConfirmTime(payDate);
                baseMapper.insert(entity);
                break;
            }
        }
        payContractList.stream().forEach(contract -> {
            //更新付款阶段付款
            List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                    .eq(ContractPaymentSchedule::getContractId,contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus,2)
                    .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 2)
                    .orderByAsc(ContractPaymentSchedule::getCreateTime));
            if (ArrayUtil.isNotEmpty(scheduleList.toArray())){
                BigDecimal remain = addDTO.getTransationAmount();
                for (ContractPaymentSchedule schedule:scheduleList) {
            if (ArrayUtil.isNotEmpty(scheduleList.toArray())) {
                BigDecimal remain = transtionAmount;
                for (ContractPaymentSchedule schedule : scheduleList) {
                    BigDecimal lastRemain = remain;
                    remain = remain.subtract(StrUtil.equals(schedule.getPaymentStatus()+"","0")?schedule.getPlannedAmount():
                    remain = remain.subtract(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount() :
                            schedule.getPlannedAmount().subtract(schedule.getActualAmount()));
                    if (remain.compareTo(new BigDecimal("0"))>=0){
                    if (remain.compareTo(new BigDecimal("0")) >= 0) {
                        schedule.setActualAmount(schedule.getPlannedAmount());
                        schedule.setPaymentDate(addDTO.getConfirmTime());
                        schedule.setPaymentDate(payDate);
                        schedule.setPaymentStatus(2);
                        contractPaymentScheduleMapper.updateById(schedule);
                        //查询是否有当前逾期
                        CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId,schedule.getId())
                                .eq(CurrentOverdue::getContractId,schedule.getContractId()).last("limit 1"));
                        if (ObjUtil.isNotNull(currentOverdue)){
                        CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                        if (ObjUtil.isNotNull(currentOverdue)) {
                            //新增逾期历史
                            HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue,HistoryOverdue.class,"id");
                            historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                            HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                            historyOverdue.setPaymentTime(payDate);
                            historyOverdue.setCompId(schedule.getCompId());
                            historyOverdueMapper.insert(historyOverdue);
                            //删除当前逾期
                            currentOverdueMapper.deleteById(currentOverdue);
                        }
                    }else {
                        schedule.setActualAmount(StrUtil.equals(schedule.getPaymentStatus()+"","0")?schedule.getPlannedAmount().add(remain):
                    } else {
                        schedule.setActualAmount(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount().add(remain) :
                                schedule.getActualAmount().add(lastRemain));
                        schedule.setPaymentDate(addDTO.getConfirmTime());
                        schedule.setPaymentDate(payDate);
                        schedule.setPaymentStatus(1);
                        contractPaymentScheduleMapper.updateById(schedule);
                        //查询是否有当前逾期
                        CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId,schedule.getId())
                                .eq(CurrentOverdue::getContractId,schedule.getContractId()).last("limit 1"));
                        if (ObjUtil.isNotNull(currentOverdue)){
                        CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                                .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
                        if (ObjUtil.isNotNull(currentOverdue)) {
                            //新增逾期历史
                            HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue,HistoryOverdue.class,"id");
                            HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                            historyOverdue.setReceivableAmount(lastRemain);
                            historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                            historyOverdue.setPaymentTime(payDate);
                            historyOverdue.setCompId(schedule.getCompId());
                            historyOverdueMapper.insert(historyOverdue);
                            //查询历史已付逾期金额
                            List<HistoryOverdue> historyOverdueList = historyOverdueMapper.selectList(Wrappers.<HistoryOverdue>lambdaQuery().eq(HistoryOverdue::getScheduleId,currentOverdue.getScheduleId()));
                            BigDecimal hisTotal = historyOverdueList.stream().map(item->item.getReceivableAmount()).reduce(BigDecimal.ZERO,BigDecimal::add);
                            List<HistoryOverdue> historyOverdueList = historyOverdueMapper.selectList(Wrappers.<HistoryOverdue>lambdaQuery().eq(HistoryOverdue::getScheduleId, currentOverdue.getScheduleId()));
                            BigDecimal hisTotal = historyOverdueList.stream().map(item -> item.getReceivableAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                            //更新当前逾期
                            currentOverdue.setReceivableAmount(schedule.getPlannedAmount().subtract(hisTotal));
                            currentOverdueMapper.updateById(currentOverdue);
@@ -154,70 +661,107 @@
                    }
                }
            }
            //更新合同已付款
            BigDecimal paid = new BigDecimal("0");
            if (ObjUtil.isNotNull(contract.getPaidAmount())){
                paid = contract.getPaidAmount();
            }
            paid = paid.add(addDTO.getTransationAmount());
            contract.setPaidAmount(paid);
            if (paid.compareTo(contract.getAmount())>0){
                contract.setPaidAmount(contract.getAmount());
            }
            contractService.updateById(contract);
        }
        //转出
        if (StrUtil.equals(addDTO.getInOrOut(),"2")){
            PaymentConfirm entity = new PaymentConfirm();
            entity.setContractId(contract.getId());
            entity.setContractName(contract.getContractName());
            entity.setContractNo(addDTO.getContractNo());
            entity.setBusGuestId(customer.getId());
            entity.setBusGuestName(customer.getCompanyName());
            entity.setBusinessType("");
            entity.setTransationAmount(addDTO.getTransationAmount());
            BigDecimal newtotal = addDTO.getTransationAmount().multiply(new BigDecimal("-1")).add(lastConfirm.getTotalAmount());
            if (newtotal.compareTo(new BigDecimal("0"))>0){
                entity.setAdvanceAmount(newtotal);
                entity.setTotalAmount(newtotal);
            }else if (newtotal.compareTo(new BigDecimal("0"))==0){
                entity.setTotalAmount(newtotal);
            }else {
                return R.failed("当前客户余额为"+lastConfirm.getTotalAmount()+"不足以满足当前发生金额,无法操作");
            }
            entity.setConfirmTime(new Date());
            baseMapper.insert(entity);
        }
        // 查询所有付款阶段是否都付款完成
        List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId,contract.getId()));
        if (ArrayUtil.isNotEmpty(scheduleList.toArray())){
            if (scheduleList.stream().allMatch(item -> Objects.equals(item.getPaymentStatus(), 2))){
                contract.setContractStatus(3);
            //合同所有付款阶段
            List<ContractPaymentSchedule> payComScheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                    .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 0)
            );
            if (ArrayUtil.isNotEmpty(payComScheduleList.toArray())){
                BigDecimal payTotal = payComScheduleList.stream().map(item->StrUtil.equals(item.getPaymentStatus() + "", "0") ? item.getPlannedAmount() :
                        item.getActualAmount()).reduce(BigDecimal.ZERO,BigDecimal::add);
                contract.setPaidAmount(payTotal);
                if (payComScheduleList.stream().allMatch(item -> Objects.equals(item.getPaymentStatus(), 2))) {
                    contract.setContractStatus(3);
                }
                contractService.updateById(contract);
            };
                if (contract.getAmount().compareTo(contract.getPaidAmount()) == 0) {
                    payCompleteContractList.add(contract);
                }
                //付款 且 付款未全付
                if (contract.getAmount().compareTo(contract.getPaidAmount()) > 0) {
                    payNoCompleteContractList.add(contract);
                }
            }
        });
        //客户预付有剩余 且 有预付款的合同
        if (transtionRemainAmount.compareTo(new BigDecimal("0")) > 0) {
            if (ArrayUtil.isNotEmpty(payNoCompleteContractList.toArray())){
                //余额 放到付款未完成合同 预收
                Contract lastContract = payNoCompleteContractList.get(payNoCompleteContractList.size() - 1);
                //保存明细
                saveNewPaymentConfirm(customer,record,lastContract,transtionRemainAmount,payDate);
            }
            if (ArrayUtil.isEmpty(payNoCompleteContractList.toArray())&&ArrayUtil.isNotEmpty(advanceContractList.toArray())){
                //客户预付有剩余 没有预付款的合同
                Contract lastContract = payNoCompleteContractList.get(payNoCompleteContractList.size() - 1);
                //保存明细
                saveNewPaymentConfirm(customer,record,lastContract,transtionRemainAmount,payDate);
            }
            if (ArrayUtil.isEmpty(payNoCompleteContractList.toArray())&&ArrayUtil.isEmpty(advanceContractList.toArray())
                    &&ArrayUtil.isNotEmpty(payCompleteContractList.toArray())) {
                //客户预付有剩余 没有预付款的合同
                Contract lastContract = payCompleteContractList.get(payCompleteContractList.size() - 1);
                //保存明细
                saveNewPaymentConfirm(customer,record,lastContract,transtionRemainAmount,payDate);
            }
        }
        return R.ok();
    }
    @Override
    public R syncPaymentRecepit() {
    private Boolean savePaymentSlip(BusinessCustomer customer, JSONObject record) {
        PaymentSlip slip = new PaymentSlip();
        slip.setBusGuestId(customer.getId());
        slip.setBusGuestName(customer.getCompanyName());
        slip.setPaymentTime(ObjUtil.isNotNull(record.get("billDate"))?
                DateUtil.parse(record.getString("billDate"), DatePattern.NORM_DATETIME_FORMAT):new Date());
        slip.setPaymentAmount(ObjUtil.isNotNull(record.get("bodyItemOriTaxExcludedAmount"))?record.getBigDecimal("bodyItemOriTaxExcludedAmount"):new BigDecimal("0"));
        slip.setPayType(ObjUtil.isNotNull(record.get("bodyItemSettleModeName"))?record.getString("bodyItemSettleModeName"):"");
        if (ObjUtil.isNotNull(record.get("code"))){
            slip.setPaymentNumber(record.getString("code"));
            PaymentSlip paymentSlip = paymentSlipMapper.selectOne(Wrappers.<PaymentSlip>lambdaQuery().eq(PaymentSlip::getPaymentNumber,slip.getPaymentNumber()));
            if (ObjUtil.isNull(paymentSlip)) {
                paymentSlipMapper.insert(slip);
                return false;
            }
        }
        return true;
    }
        JSONObject params = new JSONObject();
        params.put("pageIndex", 1);
        params.put("pageSize", 999);
        params.put("open_billDate_begin", DateUtil.offsetDay(new Date(),-1) + " 00:00:00");
        params.put("open_billDate_begin", DateUtil.today() + " 00:00:00");
        //单据状态已审批
        params.put("verifyState", new String[]{"2"});
        //往来对象客户
        params.put("objectType", new String[]{"1"});
        //单位
//        JSONObject simpleMap = new JSONObject();
//        simpleMap.put("financeOrg.code", bipCode);
//        params.put("simple", simpleMap);
        HttpUtil.post(url+"/yonbip/EFI/collection/list",params.toJSONString());
    public void saveNewPaymentConfirm(BusinessCustomer customer,JSONObject record,Contract contract,BigDecimal transtionRemainAmount
        ,Date payDate){
        PaymentConfirm entity = new PaymentConfirm();
        entity.setContractId(contract.getId());
        entity.setContractName(contract.getContractName());
        entity.setContractNo(contract.getContractNo());
        PaymentConfirm lastConfirm = baseMapper.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();
        }
        return null;
        if (ObjUtil.isNotNull(lastConfirm)) {
            entity.setScheduleId(lastConfirm.getScheduleId());
            entity.setScheduleName(lastConfirm.getScheduleName());
        }
        entity.setBusGuestId(customer.getId());
        entity.setBusGuestName(customer.getCompanyName());
        entity.setBusinessType("客户付款");
        if (ObjUtil.isNotNull(record)){
            entity.setIsBip(1);
            entity.setPaymentCode(record.getString("code"));
            entity.setPayType(record.get("bodyItemSettleModeName") != null ? record.getString("bodyItemSettleModeName").contains("承兑汇票") ? 1 : 0 : null);
            entity.setBipId(record.getString("id"));
        }
        entity.setConfirmTime(payDate);
        entity.setTransationAmount(transtionRemainAmount);
        entity.setTotalAmount(transtionRemainAmount.add(lastTotal));
        if (entity.getTotalAmount().compareTo(new BigDecimal("0"))>0){
            entity.setAdvanceAmount(entity.getTotalAmount());
        }else if (entity.getTotalAmount().compareTo(new BigDecimal("0"))<0){
            entity.setReceivableAmount(entity.getTotalAmount().multiply(new BigDecimal("-1")));
        }
        baseMapper.insert(entity);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/utils/SignHelper.java
New file
@@ -0,0 +1,46 @@
package com.by4cloud.platformx.business.utils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
/**
 * 请求开放平台套件授权相关接口的加签类
 * SignHelper
 *
 * syt
 * 2026年5月20日 10:31:44
 */
public class SignHelper {
    /**
     * 按参数名排序后依次拼接参数名称与数值, 之后对该字符串使用 HmacSHA256 加签, 加签结果进行 base 64 返回
     *
     */
    public static String sign(Map<String, Object> params, String suiteSecret) throws
            NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        Map<String, Object> treeMap;
        if (params instanceof TreeMap) {
            treeMap = params;
        } else {
            treeMap = new TreeMap<>(params);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(suiteSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = Base64.getEncoder().encodeToString(signData);
        return URLEncoder.encode(base64String, "UTF-8");
    }
}
platformx-business-finance-biz/src/main/resources/mapper/BipRequestRecordMapper.xml
New file
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.by4cloud.platformx.business.mapper.BipRequestRecordMapper">
  <resultMap id="bipRequestRecordMap" type="com.by4cloud.platformx.business.entity.BipRequestRecord">
        <id property="id" column="id"/>
        <result property="compId" column="comp_id"/>
        <result property="interfaceName" column="interface_name"/>
        <result property="requestParams" column="request_params"/>
        <result property="responseCode" column="response_code"/>
        <result property="responseParams" column="response_params"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="delFlag" column="del_flag"/>
  </resultMap>
</mapper>
platformx-business-finance-biz/src/main/resources/mapper/ContractOutBoundMapper.xml
@@ -16,6 +16,7 @@
        <result property="outBoundTime" column="out_bound_time"/>
        <result property="subjectMatterCode" column="subject_matter_code"/>
        <result property="subjectMatterName" column="subject_matter_name"/>
          <result property="outBoundId" column="out_bound_id"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
platformx-business-finance-biz/src/main/resources/mapper/PaymentSlipMapper.xml
New file
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.by4cloud.platformx.business.mapper.PaymentSlipMapper">
    <resultMap id="paymentSlipMap" type="com.by4cloud.platformx.business.entity.PaymentSlip">
        <id property="id" column="id"/>
        <result property="compId" column="comp_id"/>
        <result property="busGuestId" column="bus_guest_id"/>
        <result property="busGuestName" column="bus_guest_name"/>
        <result property="businessType" column="business_type"/>
        <result property="gatheringAccount" column="gathering_account"/>
        <result property="payType" column="pay_type"/>
        <result property="paymentAccount" column="payment_account"/>
        <result property="paymentAmount" column="payment_amount"/>
        <result property="paymentNumber" column="payment_number"/>
        <result property="paymentTime" column="payment_time"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>
</mapper>
platformx-business-finance-biz/src/main/resources/template/ymjjgclht.doc
Binary files differ