19个文件已修改
18个文件已添加
2906 ■■■■■ 已修改文件
platformx-boot/src/main/resources/application-dev.yml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AnalysisCommonDTO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | 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/ContractAmountAnalysisCompVo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractAmountAnalysisVo.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisAreaVo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisCompVo.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisVo.java 106 ●●●●● 补丁 | 查看 | 原始文档 | 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/controller/StatisticController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | 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/ContractMapper.java 41 ●●●●● 补丁 | 查看 | 原始文档 | 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/StatisticService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | 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/service/impl/PaymentOffsetServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/StatisticServiceImpl.java 287 ●●●●● 补丁 | 查看 | 原始文档 | 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/ContractMapper.xml 711 ●●●●● 补丁 | 查看 | 原始文档 | 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,19 @@
#bip 配置
bip:
  url:
  codes: 111111111111111111111111,222222222222222222
  appKey:
  appSecret:
# 文件上传配置
file:
  local:
    base-path: D:\\Users\\platformx\\Downloads\\img
# 5家单位id
dept:
  smj: 2056555602756063234
  sgb: 2056556196124250113
  jxc: 2056556317461270529
  tfgs: 2056556421857497090
  ymj: 2056556535640576002
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/AnalysisCommonDTO.java
New file
@@ -0,0 +1,10 @@
package com.by4cloud.platformx.business.dto;
import lombok.Data;
@Data
public class AnalysisCommonDTO {
    private String year;
}
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/承兑 2/抵抹账
     */
    @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/ContractAmountAnalysisCompVo.java
New file
@@ -0,0 +1,16 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class ContractAmountAnalysisCompVo {
    private String yf;
    private String je;
    private String tb;
    private String hb;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractAmountAnalysisVo.java
New file
@@ -0,0 +1,35 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class ContractAmountAnalysisVo {
    private String compName;
    private String month1;
    private String month2;
    private String month3;
    private String month4;
    private String month5;
    private String month6;
    private String month7;
    private String month8;
    private String month9;
    private String month10;
    private String month11;
    private String month12;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisAreaVo.java
New file
@@ -0,0 +1,31 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class ContractIncomeAnalysisAreaVo {
    private String areaId;
    private String areaName;
    private String sgbze;
    private String sgbzb;
    private String smjze;
    private String smjzb;
    private String jxcze;
    private String jxczb;
    private String tfze;
    private String tfzb;
    private String ymjze;
    private String ymjzb;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisCompVo.java
New file
@@ -0,0 +1,17 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class ContractIncomeAnalysisCompVo {
    private String yf;
    private String sr;
    private String xh;
    private String cd;
    private String qt;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractIncomeAnalysisVo.java
New file
@@ -0,0 +1,106 @@
package com.by4cloud.platformx.business.vo;
import lombok.Data;
@Data
public class ContractIncomeAnalysisVo {
    private String compName;
    private String srMonth1;
    private String xhMonth1;
    private String cdMonth1;
    private String qtMonth1;
    private String srMonth2;
    private String xhMonth2;
    private String cdMonth2;
    private String qtMonth2;
    private String srMonth3;
    private String xhMonth3;
    private String cdMonth3;
    private String qtMonth3;
    private String srMonth4;
    private String xhMonth4;
    private String cdMonth4;
    private String qtMonth4;
    private String srMonth5;
    private String xhMonth5;
    private String cdMonth5;
    private String qtMonth5;
    private String srMonth6;
    private String xhMonth6;
    private String cdMonth6;
    private String qtMonth6;
    private String srMonth7;
    private String xhMonth7;
    private String cdMonth7;
    private String qtMonth7;
    private String srMonth8;
    private String xhMonth8;
    private String cdMonth8;
    private String qtMonth8;
    private String srMonth9;
    private String xhMonth9;
    private String cdMonth9;
    private String qtMonth9;
    private String srMonth10;
    private String xhMonth10;
    private String cdMonth10;
    private String qtMonth10;
    private String srMonth11;
    private String xhMonth11;
    private String cdMonth11;
    private String qtMonth11;
    private String srMonth12;
    private String xhMonth12;
    private String cdMonth12;
    private String qtMonth12;
}
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/controller/StatisticController.java
New file
@@ -0,0 +1,114 @@
package com.by4cloud.platformx.business.controller;
import com.by4cloud.platformx.business.dto.AnalysisCommonDTO;
import com.by4cloud.platformx.business.entity.SalesMan;
import com.by4cloud.platformx.business.service.StatisticService;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * 统计模块
 *
 * @author syt
 * @date 2026年5月22日 09:41:29
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/statistic" )
@Tag(description = "statistic" , name = "统计模块" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class StatisticController {
    private final StatisticService statisticService;
    /**
     * 合同金额数据分析
     * @return R
     */
    @PostMapping("/contractAmountAnalysis")
    public R contractAmountAnalysis(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysis(commonDTO);
    }
    /**
     * 子公司合同金额数据分析
     * @return R
     */
    @PostMapping("/contractAmountAnalysisByComp")
    public R contractAmountAnalysisByComp(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisByComp(commonDTO);
    }
    /**
     * 收入数据分析
     * @return R
     */
    @PostMapping("/contractIncomeAnalysis")
    public R contractIncomeAnalysis(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractIncomeAnalysis(commonDTO);
    }
    /**
     * 子公司收入数据分析
     * @return R
     */
    @PostMapping("/contractIncomeAnalysisByComp")
    public R contractIncomeAnalysisByComp(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractIncomeAnalysisByComp(commonDTO);
    }
    /**
     * 分区域合同金额统计
     * @return R
     */
    @PostMapping("/contractAmountAnalysisByArea")
    public R contractAmountAnalysisByArea(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisByArea(commonDTO);
    }
    /**
     * 分行业合同金额统计
     * @return R
     */
    @PostMapping("/contractAmountAnalysisByIndustry")
    public R contractAmountAnalysisByIndustry(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisByIndustry(commonDTO);
    }
    /**
     * 分市场合同金额统计
     * @return R
     */
    @PostMapping("/contractAmountAnalysisByMarket")
    public R contractAmountAnalysisByMarket(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisByMarket(commonDTO);
    }
    /**
     * 分供应属性业务合同金额统计
     * @return R
     */
    @PostMapping("/contractAmountAnalysisBySpcBus")
    public R contractAmountAnalysisBySpcBus(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisBySpcBus(commonDTO);
    }
    /**
     * 分出口业务合同金额统计
     * @return R
     */
    @PostMapping("/contractAmountAnalysisByExportBus")
    public R contractAmountAnalysisByExportBus(@RequestBody AnalysisCommonDTO commonDTO) {
        return statisticService.contractAmountAnalysisByExportBus(commonDTO);
    }
}
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/ContractMapper.java
@@ -1,13 +1,16 @@
package com.by4cloud.platformx.business.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.by4cloud.platformx.business.dto.AnalysisCommonDTO;
import com.by4cloud.platformx.business.dto.CreditSalesQueryDTO;
import com.by4cloud.platformx.business.entity.Contract;
import com.by4cloud.platformx.business.vo.ContractCreditSalesPageVo;
import com.by4cloud.platformx.business.vo.*;
import com.by4cloud.platformx.common.data.datascope.DataScope;
import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * @author 28254
@@ -15,4 +18,40 @@
@Mapper
public interface ContractMapper extends PlatformxBaseMapper<Contract> {
    Page<ContractCreditSalesPageVo> pageByCredit(Page page, @Param("queryDTO") CreditSalesQueryDTO queryDTO, DataScope comp_id);
    List<ContractAmountAnalysisVo> contractAmountAnalysis(@Param("queryDTO")AnalysisCommonDTO commonDTO,@Param("compIds")List<Long> compIds);
    List<ContractIncomeAnalysisVo> contractIncomeAnalysis(@Param("queryDTO")AnalysisCommonDTO commonDTO,@Param("compIds")List<Long> compIds);
    void setSession();
    List<ContractIncomeAnalysisCompVo> contractIncomeAnalysisByComp(@Param("queryDTO")AnalysisCommonDTO commonDTO,@Param("compId") Long compId);
    List<ContractIncomeAnalysisAreaVo> contractAmountAnalysisByArea(@Param("queryDTO")AnalysisCommonDTO commonDTO
                                                                    ,@Param("compIds")List<Long> compIds,@Param("smjCompId") Long smj,
                                                                    @Param("sgbCompId")Long sgb, @Param("jxcCompId")Long jxc,
                                                                    @Param("tfCompId") Long tfgs,@Param("ymjCompId") Long ymj);
    List<ContractIncomeAnalysisAreaVo> contractAmountAnalysisByIndustry(@Param("queryDTO")AnalysisCommonDTO commonDTO
            ,@Param("compIds")List<Long> compIds,@Param("smjCompId") Long smj,
                                                                        @Param("sgbCompId")Long sgb, @Param("jxcCompId")Long jxc,
                                                                        @Param("tfCompId") Long tfgs,@Param("ymjCompId") Long ymj);
    List<ContractIncomeAnalysisAreaVo> contractAmountAnalysisByMarket(@Param("queryDTO")AnalysisCommonDTO commonDTO
            ,@Param("compIds")List<Long> compIds,@Param("smjCompId") Long smj,
                                                                      @Param("sgbCompId")Long sgb, @Param("jxcCompId")Long jxc,
                                                                      @Param("tfCompId") Long tfgs,@Param("ymjCompId") Long ymj);
    List<ContractIncomeAnalysisAreaVo> contractAmountAnalysisBySpcBus(@Param("queryDTO")AnalysisCommonDTO commonDTO
            ,@Param("compIds")List<Long> compIds,@Param("smjCompId") Long smj,
                                                                      @Param("sgbCompId")Long sgb, @Param("jxcCompId")Long jxc,
                                                                      @Param("tfCompId") Long tfgs,@Param("ymjCompId") Long ymj);
    List<ContractIncomeAnalysisAreaVo> contractAmountAnalysisByExportBus(@Param("queryDTO")AnalysisCommonDTO commonDTO
            ,@Param("compIds")List<Long> compIds,@Param("smjCompId") Long smj,
                                                                         @Param("sgbCompId")Long sgb, @Param("jxcCompId")Long jxc,
                                                                         @Param("tfCompId") Long tfgs,@Param("ymjCompId") Long ymj);
    List<ContractAmountAnalysisCompVo> contractAmountAnalysisByComp(@Param("queryDTO")AnalysisCommonDTO commonDTO,@Param("compId") Long compId);
}
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/StatisticService.java
New file
@@ -0,0 +1,24 @@
package com.by4cloud.platformx.business.service;
import com.by4cloud.platformx.business.dto.AnalysisCommonDTO;
import com.by4cloud.platformx.common.core.util.R;
public interface StatisticService {
    R contractAmountAnalysis(AnalysisCommonDTO commonDTO);
    R contractIncomeAnalysis(AnalysisCommonDTO commonDTO);
    R contractIncomeAnalysisByComp(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisByArea(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisByIndustry(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisByMarket(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisBySpcBus(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisByExportBus(AnalysisCommonDTO commonDTO);
    R contractAmountAnalysisByComp(AnalysisCommonDTO commonDTO);
}
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/service/impl/PaymentOffsetServiceImpl.java
@@ -55,6 +55,7 @@
        entity.setConfirmTime(paymentOffset.getOffsetTime());
        entity.setTransationAmount(paymentOffset.getOffsetAmount());
        entity.setTotalAmount(paymentOffset.getOffsetAmount().add(lastTotal));
        entity.setPayType(2);
        paymentConfirmMapper.insert(entity);
        //更新付款阶段付款
        List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/StatisticServiceImpl.java
New file
@@ -0,0 +1,287 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.by4cloud.platformx.admin.api.entity.SysDept;
import com.by4cloud.platformx.admin.api.entity.SysDictItem;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.admin.api.feign.RemoteDictService;
import com.by4cloud.platformx.business.dto.AnalysisCommonDTO;
import com.by4cloud.platformx.business.mapper.ContractMapper;
import com.by4cloud.platformx.business.service.StatisticService;
import com.by4cloud.platformx.business.vo.*;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
@RequiredArgsConstructor
public class StatisticServiceImpl implements StatisticService {
    private final ContractMapper contractMapper;
    private final RemoteDeptService remoteDeptService;
    private final RemoteDictService remoteDictService;
    @Value("${dept.smj}")
    private String smj;
    @Value("${dept.sgb}")
    private String sgb;
    @Value("${dept.jxc}")
    private String jxc;
    @Value("${dept.tfgs}")
    private String tfgs;
    @Value("${dept.ymj}")
    private String ymj;
    @Override
    public R contractAmountAnalysis(AnalysisCommonDTO commonDTO) {
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractAmountAnalysisVo> contractAmountAnalysisVoList = contractMapper.contractAmountAnalysis(commonDTO,compIds);
        return R.ok(contractAmountAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisByComp(AnalysisCommonDTO commonDTO) {
        List<ContractAmountAnalysisCompVo> contractIncomeAnalysisVoList = contractMapper.contractAmountAnalysisByComp(commonDTO, SecurityUtils.getUser().getCompId());
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractIncomeAnalysis(AnalysisCommonDTO commonDTO) {
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisVo> contractIncomeAnalysisVoList = contractMapper.contractIncomeAnalysis(commonDTO,compIds);
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractIncomeAnalysisByComp(AnalysisCommonDTO commonDTO) {
        List<ContractIncomeAnalysisCompVo> contractIncomeAnalysisVoList = contractMapper.contractIncomeAnalysisByComp(commonDTO, SecurityUtils.getUser().getCompId());
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisByArea(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("company_area");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisAreaVo> contractIncomeAnalysisVoList = items.stream().map(item -> {
            ContractIncomeAnalysisAreaVo analysisAreaVo = new ContractIncomeAnalysisAreaVo();
            analysisAreaVo.setAreaId(item.getItemValue());
            analysisAreaVo.setAreaName(item.getLabel());
            return analysisAreaVo;
        }).collect(Collectors.toList());
        List<ContractIncomeAnalysisAreaVo> statisticList = contractMapper.contractAmountAnalysisByArea(commonDTO
                ,compIds,Long.valueOf(smj),Long.valueOf(sgb),Long.valueOf(jxc),Long.valueOf(tfgs),Long.valueOf(ymj));
        contractIncomeAnalysisVoList.stream().forEach(vo1->{
            statisticList.stream().forEach(vo2->{
                if (StrUtil.equals(vo1.getAreaId(),vo2.getAreaId())){
                    vo1.setJxczb(vo2.getJxczb());
                    vo1.setJxcze(vo2.getJxcze());
                    vo1.setSgbzb(vo2.getSgbzb());
                    vo1.setSgbze(vo2.getSgbze());
                    vo1.setSmjzb(vo2.getSmjzb());
                    vo1.setSmjze(vo2.getSmjze());
                    vo1.setTfzb(vo2.getTfzb());
                    vo1.setTfze(vo2.getTfze());
                    vo1.setYmjzb(vo2.getYmjzb());
                    vo1.setYmjze(vo2.getYmjze());
                }
            });
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisByIndustry(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("industry_sector");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisAreaVo> contractIncomeAnalysisVoList = items.stream().map(item -> {
            ContractIncomeAnalysisAreaVo analysisAreaVo = new ContractIncomeAnalysisAreaVo();
            analysisAreaVo.setAreaId(item.getItemValue());
            analysisAreaVo.setAreaName(item.getLabel());
            return analysisAreaVo;
        }).collect(Collectors.toList());
        List<ContractIncomeAnalysisAreaVo> statisticList = contractMapper.contractAmountAnalysisByIndustry(commonDTO
                ,compIds,Long.valueOf(smj),Long.valueOf(sgb),Long.valueOf(jxc),Long.valueOf(tfgs),Long.valueOf(ymj));
        contractIncomeAnalysisVoList.stream().forEach(vo1->{
            statisticList.stream().forEach(vo2->{
                if (StrUtil.equals(vo1.getAreaId(),vo2.getAreaId())){
                    vo1.setJxczb(vo2.getJxczb());
                    vo1.setJxcze(vo2.getJxcze());
                    vo1.setSgbzb(vo2.getSgbzb());
                    vo1.setSgbze(vo2.getSgbze());
                    vo1.setSmjzb(vo2.getSmjzb());
                    vo1.setSmjze(vo2.getSmjze());
                    vo1.setTfzb(vo2.getTfzb());
                    vo1.setTfze(vo2.getTfze());
                    vo1.setYmjzb(vo2.getYmjzb());
                    vo1.setYmjze(vo2.getYmjze());
                }
            });
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisByMarket(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("market_type");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisAreaVo> contractIncomeAnalysisVoList = items.stream().map(item -> {
            ContractIncomeAnalysisAreaVo analysisAreaVo = new ContractIncomeAnalysisAreaVo();
            analysisAreaVo.setAreaId(item.getItemValue());
            analysisAreaVo.setAreaName(item.getLabel());
            return analysisAreaVo;
        }).collect(Collectors.toList());
        List<ContractIncomeAnalysisAreaVo> statisticList = contractMapper.contractAmountAnalysisByMarket(commonDTO
                ,compIds,Long.valueOf(smj),Long.valueOf(sgb),Long.valueOf(jxc),Long.valueOf(tfgs),Long.valueOf(ymj));
        contractIncomeAnalysisVoList.stream().forEach(vo1->{
            statisticList.stream().forEach(vo2->{
                if (StrUtil.equals(vo1.getAreaId(),vo2.getAreaId())){
                    vo1.setJxczb(vo2.getJxczb());
                    vo1.setJxcze(vo2.getJxcze());
                    vo1.setSgbzb(vo2.getSgbzb());
                    vo1.setSgbze(vo2.getSgbze());
                    vo1.setSmjzb(vo2.getSmjzb());
                    vo1.setSmjze(vo2.getSmjze());
                    vo1.setTfzb(vo2.getTfzb());
                    vo1.setTfze(vo2.getTfze());
                    vo1.setYmjzb(vo2.getYmjzb());
                    vo1.setYmjze(vo2.getYmjze());
                }
            });
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisBySpcBus(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("supply_attribute");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisAreaVo> contractIncomeAnalysisVoList = items.stream().map(item -> {
            ContractIncomeAnalysisAreaVo analysisAreaVo = new ContractIncomeAnalysisAreaVo();
            analysisAreaVo.setAreaId(item.getItemValue());
            analysisAreaVo.setAreaName(item.getLabel());
            return analysisAreaVo;
        }).collect(Collectors.toList());
        List<ContractIncomeAnalysisAreaVo> statisticList = contractMapper.contractAmountAnalysisBySpcBus(commonDTO
                ,compIds,Long.valueOf(smj),Long.valueOf(sgb),Long.valueOf(jxc),Long.valueOf(tfgs),Long.valueOf(ymj));
        contractIncomeAnalysisVoList.stream().forEach(vo1->{
            statisticList.stream().forEach(vo2->{
                if (StrUtil.equals(vo1.getAreaId(),vo2.getAreaId())){
                    vo1.setJxczb(vo2.getJxczb());
                    vo1.setJxcze(vo2.getJxcze());
                    vo1.setSgbzb(vo2.getSgbzb());
                    vo1.setSgbze(vo2.getSgbze());
                    vo1.setSmjzb(vo2.getSmjzb());
                    vo1.setSmjze(vo2.getSmjze());
                    vo1.setTfzb(vo2.getTfzb());
                    vo1.setTfze(vo2.getTfze());
                    vo1.setYmjzb(vo2.getYmjzb());
                    vo1.setYmjze(vo2.getYmjze());
                }
            });
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
    @Override
    public R contractAmountAnalysisByExportBus(AnalysisCommonDTO commonDTO) {
        R<List<SysDictItem>> r = remoteDictService.getDictByType("export_attr");
        List<SysDictItem> items = r.getData();
        if (ArrayUtil.isEmpty(items.toArray())){
            return R.failed("区域字段获取异常");
        }
        List<Long> compIds = new ArrayList<>();
        compIds.add(Long.valueOf(sgb));
        compIds.add(Long.valueOf(smj));
        compIds.add(Long.valueOf(tfgs));
        compIds.add(Long.valueOf(ymj));
        compIds.add(Long.valueOf(jxc));
        List<ContractIncomeAnalysisAreaVo> contractIncomeAnalysisVoList = items.stream().map(item -> {
            ContractIncomeAnalysisAreaVo analysisAreaVo = new ContractIncomeAnalysisAreaVo();
            analysisAreaVo.setAreaId(item.getItemValue());
            analysisAreaVo.setAreaName(item.getLabel());
            return analysisAreaVo;
        }).collect(Collectors.toList());
        List<ContractIncomeAnalysisAreaVo> statisticList = contractMapper.contractAmountAnalysisByExportBus(commonDTO
                ,compIds,Long.valueOf(smj),Long.valueOf(sgb),Long.valueOf(jxc),Long.valueOf(tfgs),Long.valueOf(ymj));
        contractIncomeAnalysisVoList.stream().forEach(vo1->{
            statisticList.stream().forEach(vo2->{
                if (StrUtil.equals(vo1.getAreaId(),vo2.getAreaId())){
                    vo1.setJxczb(vo2.getJxczb());
                    vo1.setJxcze(vo2.getJxcze());
                    vo1.setSgbzb(vo2.getSgbzb());
                    vo1.setSgbze(vo2.getSgbze());
                    vo1.setSmjzb(vo2.getSmjzb());
                    vo1.setSmjze(vo2.getSmjze());
                    vo1.setTfzb(vo2.getTfzb());
                    vo1.setTfze(vo2.getTfze());
                    vo1.setYmjzb(vo2.getYmjzb());
                    vo1.setYmjze(vo2.getYmjze());
                }
            });
        });
        return R.ok(contractIncomeAnalysisVoList);
    }
}
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/ContractMapper.xml
@@ -4,6 +4,9 @@
<mapper namespace="com.by4cloud.platformx.business.mapper.ContractMapper">
    <update id="setSession">
        SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
    </update>
    <select id="pageByCredit" resultType="com.by4cloud.platformx.business.vo.ContractCreditSalesPageVo">
        SELECT
        id,
@@ -100,4 +103,712 @@
            </otherwise>
        </choose>
    </select>
    <select id="contractAmountAnalysis"
            resultType="com.by4cloud.platformx.business.vo.ContractAmountAnalysisVo">
        SELECT
            party_b_name AS 'compName',
                SUM(m01) AS 'month1',
                SUM(m02) AS 'month2',
                SUM(m03) AS 'month3',
                SUM(m04) AS 'month4',
                SUM(m05) AS 'month5',
                SUM(m06) AS 'month6',
                SUM(m07) AS 'month7',
                SUM(m08) AS 'month8',
                SUM(m09) AS 'month9',
                SUM(m10) AS 'month10',
                SUM(m11) AS 'month11',
                SUM(m12) AS 'month12'
        FROM (
                 SELECT
                     COALESCE(party_b, '未知甲方') AS party_b_name,
                     SUM(CASE WHEN MONTH(sign_date) = 1 THEN amount ELSE 0 END) AS m01,
                     SUM(CASE WHEN MONTH(sign_date) = 2 THEN amount ELSE 0 END) AS m02,
                     SUM(CASE WHEN MONTH(sign_date) = 3 THEN amount ELSE 0 END) AS m03,
                     SUM(CASE WHEN MONTH(sign_date) = 4 THEN amount ELSE 0 END) AS m04,
                     SUM(CASE WHEN MONTH(sign_date) = 5 THEN amount ELSE 0 END) AS m05,
                     SUM(CASE WHEN MONTH(sign_date) = 6 THEN amount ELSE 0 END) AS m06,
                     SUM(CASE WHEN MONTH(sign_date) = 7 THEN amount ELSE 0 END) AS m07,
                     SUM(CASE WHEN MONTH(sign_date) = 8 THEN amount ELSE 0 END) AS m08,
                     SUM(CASE WHEN MONTH(sign_date) = 9 THEN amount ELSE 0 END) AS m09,
                     SUM(CASE WHEN MONTH(sign_date) = 10 THEN amount ELSE 0 END) AS m10,
                     SUM(CASE WHEN MONTH(sign_date) = 11 THEN amount ELSE 0 END) AS m11,
                     SUM(CASE WHEN MONTH(sign_date) = 12 THEN amount ELSE 0 END) AS m12,
                     SUM(amount) AS total_amt
                 FROM contract
                 WHERE
                             del_flag = '0'
                         AND amount IS NOT NULL
                         AND sign_date IS NOT NULL
                         AND YEAR(sign_date) = #{queryDTO.year}
                        AND    party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        GROUP BY party_b_id, party_b
        UNION ALL
        SELECT
            '总计' AS party_b_name,
            SUM(CASE WHEN MONTH(sign_date) = 1 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 2 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 3 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 4 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 5 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 6 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 7 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 8 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 9 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 10 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 11 THEN amount ELSE 0 END),
            SUM(CASE WHEN MONTH(sign_date) = 12 THEN amount ELSE 0 END),
            SUM(amount)
        FROM contract
        WHERE
                    del_flag = '0'
                AND amount IS NOT NULL
                AND sign_date IS NOT NULL
                AND YEAR(sign_date) = #{queryDTO.year}
        AND    party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
                ) AS pivot_table
            GROUP BY party_b_name
            ORDER BY
                CASE WHEN party_b_name = '总计' THEN 1 ELSE 0 END,
        party_b_name;
    </select>
    <select id="contractIncomeAnalysis"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisVo">
        SELECT
            compName,
            SUM(CASE WHEN month_num = 1 THEN total_amount ELSE 0 END) AS 'srMonth1',
                SUM(CASE WHEN month_num = 1 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth1',
                SUM(CASE WHEN month_num = 1 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth1',
                SUM(CASE WHEN month_num = 1 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth1',
                SUM(CASE WHEN month_num = 2 THEN total_amount ELSE 0 END) AS 'srMonth2',
                SUM(CASE WHEN month_num = 2 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth2',
                SUM(CASE WHEN month_num = 2 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth2',
                SUM(CASE WHEN month_num = 2 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth2',
                SUM(CASE WHEN month_num = 3 THEN total_amount ELSE 0 END) AS 'srMonth3',
                SUM(CASE WHEN month_num = 3 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth3',
                SUM(CASE WHEN month_num = 3 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth3',
                SUM(CASE WHEN month_num = 3 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth3',
                SUM(CASE WHEN month_num = 4 THEN total_amount ELSE 0 END) AS 'srMonth4',
                SUM(CASE WHEN month_num = 4 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth4',
                SUM(CASE WHEN month_num = 4 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth4',
                SUM(CASE WHEN month_num = 4 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth4',
                SUM(CASE WHEN month_num = 5 THEN total_amount ELSE 0 END) AS 'srMonth5',
                SUM(CASE WHEN month_num = 5 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth5',
                SUM(CASE WHEN month_num = 5 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth5',
                SUM(CASE WHEN month_num = 5 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth5',
                SUM(CASE WHEN month_num = 6 THEN total_amount ELSE 0 END) AS 'srMonth6',
                SUM(CASE WHEN month_num = 6 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth6',
                SUM(CASE WHEN month_num = 6 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth6',
                SUM(CASE WHEN month_num = 6 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth6',
                SUM(CASE WHEN month_num = 7 THEN total_amount ELSE 0 END) AS 'srMonth7',
                SUM(CASE WHEN month_num = 7 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth7',
                SUM(CASE WHEN month_num = 7 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth7',
                SUM(CASE WHEN month_num = 7 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth7',
                SUM(CASE WHEN month_num = 8 THEN total_amount ELSE 0 END) AS 'srMonth8',
                SUM(CASE WHEN month_num = 8 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth8',
                SUM(CASE WHEN month_num = 8 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth8',
                SUM(CASE WHEN month_num = 8 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth8',
                SUM(CASE WHEN month_num = 9 THEN total_amount ELSE 0 END) AS 'srMonth9',
                SUM(CASE WHEN month_num = 9 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth9',
                SUM(CASE WHEN month_num = 9 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth9',
                SUM(CASE WHEN month_num = 9 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth9',
                SUM(CASE WHEN month_num = 10 THEN total_amount ELSE 0 END) AS 'srMonth10',
                SUM(CASE WHEN month_num = 10 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth10',
                SUM(CASE WHEN month_num = 10 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth10',
                SUM(CASE WHEN month_num = 10 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth10',
                SUM(CASE WHEN month_num = 11 THEN total_amount ELSE 0 END) AS 'srMonth11',
                SUM(CASE WHEN month_num = 11 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth11',
                SUM(CASE WHEN month_num = 11 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth11',
                SUM(CASE WHEN month_num = 11 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth11',
                SUM(CASE WHEN month_num = 12 THEN total_amount ELSE 0 END) AS 'srMonth12',
                SUM(CASE WHEN month_num = 12 AND pay_type = 0 THEN total_amount ELSE 0 END) AS 'xhMonth12',
                SUM(CASE WHEN month_num = 12 AND pay_type = 1 THEN total_amount ELSE 0 END) AS 'cdMonth12',
                SUM(CASE WHEN month_num = 12 AND pay_type = 2 THEN total_amount ELSE 0 END) AS 'qtMonth12'
        FROM (
                 SELECT
                     COALESCE(c.party_b, '未知单位') AS compName,
                     MONTH(confirm_time) AS month_num,
                     pay_type,
                     COALESCE(transation_amount, 0) AS total_amount
                 FROM payment_confirm pc,contract c
                 WHERE
                     pc.del_flag = '0'
                   And c.del_flag = '0'
                   AND pc.contract_id = c.id
                   AND confirm_time IS NOT NULL
                   AND transation_amount IS NOT NULL
                   AND YEAR(confirm_time) = #{queryDTO.year}
        AND    party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
             ) AS source_data
        GROUP BY compName
    </select>
    <select id="contractIncomeAnalysisByComp"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisCompVo">
        SELECT
            months.yf,
            COALESCE ( SUM( transation_amount ), 0 ) AS sr,
            COALESCE ( SUM( CASE WHEN pay_type = 0 THEN COALESCE ( transation_amount, 0 ) ELSE 0 END ), 0 ) AS xh,
            COALESCE ( SUM( CASE WHEN pay_type = 1 THEN COALESCE ( transation_amount, 0 ) ELSE 0 END ), 0 ) AS cd,
            COALESCE ( SUM( CASE WHEN pay_type = 2 THEN COALESCE ( transation_amount, 0 ) ELSE 0 END ), 0 ) AS qt
        FROM
            (
                SELECT
                    '1月' AS yf UNION ALL
                SELECT
                    '2月' UNION ALL
                SELECT
                    '3月' UNION ALL
                SELECT
                    '4月' UNION ALL
                SELECT
                    '5月' UNION ALL
                SELECT
                    '6月' UNION ALL
                SELECT
                    '7月' UNION ALL
                SELECT
                    '8月' UNION ALL
                SELECT
                    '9月' UNION ALL
                SELECT
                    '10月' UNION ALL
                SELECT
                    '11月' UNION ALL
                SELECT
                    '12月'
            ) AS months
                LEFT JOIN payment_confirm pc ON months.yf = CONCAT( MONTH ( pc.confirm_time ), '月' )
                AND pc.del_flag = '0'
                AND pc.confirm_time IS NOT NULL
                AND pc.transation_amount IS NOT NULL
                AND YEAR ( pc.confirm_time ) = #{queryDTO.year}
                AND pc.comp_id = #{compId}
        WHERE
            1 = 1
        GROUP BY
            months.yf
    </select>
    <select id="contractAmountAnalysisByArea"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisAreaVo">
        SELECT
            b.area_id,
            SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) AS sgbze,
            ROUND(
                            SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) / (
                            SELECT
                                SUM( amount )
                            FROM
                                contract
                            WHERE
                                party_b_id IN
                            <foreach collection="compIds" item="id" open="(" close=")" separator=",">
                                #{id}
                            </foreach>
                ) * 100,
                            0
                ) AS zgbzb,
            SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) AS jxcze,
            ROUND(
                            SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) / (
                            SELECT
                                SUM( amount )
                            FROM
                                contract
                            WHERE
                                party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
                ) * 100,
                            0
                ) AS jxczb ,
            SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) AS smjze,
            ROUND(
                            SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) / (
                            SELECT
                                SUM( amount )
                            FROM
                                contract
                            WHERE
                                party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
                ) * 100,
                            0
                ) AS smjzb ,
            SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) AS ymjze,
            ROUND(
                            SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) / (
                            SELECT
                                SUM( amount )
                            FROM
                                contract
                            WHERE
                                party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
                ) * 100,
                            0
                ) AS ymjzb ,
            SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) AS tfze,
            ROUND(
                            SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) / (
                            SELECT
                                SUM( amount )
                            FROM
                                contract
                            WHERE
                                party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
                ) * 100,
                            0
                ) AS tfzb
        FROM
            contract c
                JOIN business_customer b ON c.party_a_id = b.id
        WHERE
            b.area_id IS NOT NULL
        AND YEAR ( sign_date ) = #{queryDTO.year}
        GROUP BY
            b.area_id
    </select>
    <select id="contractAmountAnalysisByIndustry"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisAreaVo">
        SELECT
        b.industry_id area_id,
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) AS sgbze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS zgbzb,
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) AS jxcze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS jxczb ,
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) AS smjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS smjzb ,
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) AS ymjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS ymjzb ,
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) AS tfze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS tfzb
        FROM
        contract c
        JOIN business_customer b ON c.party_a_id = b.id
        WHERE
        b.industry_id IS NOT NULL
        AND YEAR ( sign_date ) = #{queryDTO.year}
        GROUP BY
        b.industry_id
    </select>
    <select id="contractAmountAnalysisByMarket"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisAreaVo">
        SELECT
        b.class_id area_id,
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) AS sgbze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS zgbzb,
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) AS jxcze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS jxczb ,
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) AS smjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS smjzb ,
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) AS ymjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS ymjzb ,
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) AS tfze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS tfzb
        FROM
        contract c
        JOIN business_customer b ON c.party_a_id = b.id
        WHERE
        b.class_id IS NOT NULL
        AND YEAR ( sign_date ) = #{queryDTO.year}
        GROUP BY
        b.class_id
    </select>
    <select id="contractAmountAnalysisByExportBus"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisAreaVo">
        SELECT
        b.export_service_attr area_id,
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) AS sgbze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS zgbzb,
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) AS jxcze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS jxczb ,
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) AS smjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS smjzb ,
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) AS ymjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS ymjzb ,
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) AS tfze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS tfzb
        FROM
        contract c
        JOIN business_customer b ON c.party_a_id = b.id
        WHERE
        b.export_service_attr IS NOT NULL
        AND YEAR ( sign_date ) = #{queryDTO.year}
        GROUP BY
        b.export_service_attr
    </select>
    <select id="contractAmountAnalysisBySpcBus"
            resultType="com.by4cloud.platformx.business.vo.ContractIncomeAnalysisAreaVo">
        SELECT
        c.supply_attribute area_id,
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) AS sgbze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{sgbCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS zgbzb,
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) AS jxcze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{jxcCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS jxczb ,
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) AS smjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{smjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS smjzb ,
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) AS ymjze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{ymjCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS ymjzb ,
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) AS tfze,
        ROUND(
        SUM( CASE WHEN c.party_b_id = #{tfCompId} THEN c.amount ELSE 0 END ) / (
        SELECT
        SUM( amount )
        FROM
        contract
        WHERE
        party_b_id IN
        <foreach collection="compIds" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
        ) * 100,
        0
        ) AS tfzb
        FROM
        contract c
        WHERE
        c.supply_attribute IS NOT NULL
        AND YEAR ( sign_date ) = #{queryDTO.year}
        GROUP BY
        c.supply_attribute
    </select>
    <select id="contractAmountAnalysisByComp"
            resultType="com.by4cloud.platformx.business.vo.ContractAmountAnalysisCompVo">
        SELECT
            m.stat_month AS yf,
            COALESCE(curr.total_amount, 0) AS je,
            CASE
                WHEN prev.total_amount IS NULL OR prev.total_amount = 0 THEN NULL
                ELSE ROUND(
                                (COALESCE(curr.total_amount, 0) - prev.total_amount) / prev.total_amount * 100,
                                2
                    )
                END AS hb,
            CASE
                WHEN last_year.total_amount IS NULL OR last_year.total_amount = 0 THEN NULL
                ELSE ROUND(
                                (COALESCE(curr.total_amount, 0) - last_year.total_amount) / last_year.total_amount * 100,
                                2
                    )
                END AS tb
        FROM (
                 SELECT DATE_FORMAT(MAKEDATE(${queryDTO.year}, 1), '%Y-%m') AS stat_month, 1 AS month_num
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 1 MONTH), '%Y-%m'), 2
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 2 MONTH), '%Y-%m'), 3
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 3 MONTH), '%Y-%m'), 4
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 4 MONTH), '%Y-%m'), 5
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 5 MONTH), '%Y-%m'), 6
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 6 MONTH), '%Y-%m'), 7
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 7 MONTH), '%Y-%m'), 8
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 8 MONTH), '%Y-%m'), 9
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 9 MONTH), '%Y-%m'), 10
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 10 MONTH), '%Y-%m'), 11
                 UNION ALL SELECT DATE_FORMAT(DATE_ADD(MAKEDATE(${queryDTO.year}, 1), INTERVAL 11 MONTH), '%Y-%m'), 12
             ) m
                 LEFT JOIN (
            SELECT
                DATE_FORMAT(sign_date, '%Y-%m') AS stat_month,
                SUM(amount) AS total_amount
            FROM contract
            WHERE YEAR(sign_date) = #{queryDTO.year}
                 AND party_b_id = #{compId}
            GROUP BY DATE_FORMAT(sign_date, '%Y-%m')
        ) curr ON m.stat_month = curr.stat_month
                 LEFT JOIN (
            SELECT
                DATE_FORMAT(sign_date, '%Y-%m') AS stat_month,
                MONTH(sign_date) AS month_num,
                SUM(amount) AS total_amount
            FROM contract
            WHERE YEAR(sign_date) = YEAR(CURDATE())
              AND party_b_id = #{compId}
            GROUP BY DATE_FORMAT(sign_date, '%Y-%m'), MONTH(sign_date)
        ) prev ON m.month_num = prev.month_num + 1
                 LEFT JOIN (
            SELECT
                MONTH(sign_date) AS month_num,
                SUM(amount) AS total_amount
            FROM contract
            WHERE YEAR(sign_date) = YEAR(CURDATE()) - 1
            AND party_b_id = #{compId}
            GROUP BY MONTH(sign_date)
        ) last_year ON m.month_num = last_year.month_num
        ORDER BY m.month_num
    </select>
</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