shiyunteng
15 小时以前 fca21683e1b5b906d2514082ddfbae8eb820c9ea
feat:合同模版、出库标的物、合同管理拆分
13个文件已修改
8个文件已添加
759 ■■■■ 已修改文件
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/api/feign/RemoteFlowProcessService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/constant/FlowNameEnum.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractAddDTO.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/Contract.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractTemplate.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractDetailVo.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractPaymentScheduleVo.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractTemplateController.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/CurrentOverdueController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/FlowCallBackController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/HistoryOverdueController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/ContractTemplateMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractTemplateService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java 115 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractTemplateServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-biz/src/main/resources/mapper/ContractTemplateMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/api/feign/RemoteFlowProcessService.java
New file
@@ -0,0 +1,19 @@
package com.by4cloud.platformx.business.api.feign;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.flow.task.dto.ProcessInstanceParamDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
 * @author syt
 * @date 2025年5月23日 14:29:13
 */
@FeignClient(contextId = "remoteFlowProcessService", value = "platformx-business",url = "${servers.main-url}")
public interface RemoteFlowProcessService {
    @PostMapping("/process-instance/startProcessInstance")
    R startProcessInstance(@RequestBody ProcessInstanceParamDto processInstanceParamDto);
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/constant/FlowNameEnum.java
@@ -11,8 +11,6 @@
@Getter
@AllArgsConstructor
public enum FlowNameEnum {
    项目申报("项目申报"),专利申请("专利申请"),软件著作权申报("软件著作权申报"),专利放弃申请("专利放弃申请"),项目变更申请("项目变更申请"),
    项目验收申请("项目验收申请"),成果奖励申报("成果奖励申报"),人才奖励申报("人才奖励申报"),成果奖励申报1("成果奖励申报1"),
    科技进步奖申报("科技进步奖申报"),项目应用证明申报("项目应用证明申报");
    private String name;
    合同审批("合同审批");
    private String name;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractAddDTO.java
@@ -1,11 +1,9 @@
package com.by4cloud.platformx.business.dto;
import com.by4cloud.platformx.business.entity.ContractPaymentSchedule;
import com.by4cloud.platformx.business.entity.ContractSubjectMatter;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@@ -60,8 +58,11 @@
    @Schema(description = "生效日期")
    private String effectiveDate;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
    @Schema(description = "交付周期")
    private Integer deliveryCycle;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Schema(description = "到期日期")
    private String expirationDate;
@@ -71,6 +72,9 @@
    @Schema(description = "备注")
    private String remark;
    @Schema(description = "模版ID")
    private Long templateId;
    private List<ContractPaymentScheduleAddDTO> contractPaymentSchedule;
    private List<ContractSubjectMatterAddDTO> contractSubjectMatter;
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/Contract.java
@@ -94,8 +94,8 @@
    @Column(columnDefinition = "int default 0 comment '交付周期'")
    private Integer deliveryCycle;
    @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 expirationDate;
@@ -143,6 +143,10 @@
    @Column(columnDefinition = "VARCHAR(128) comment '下一阶段'")
    private String nextScheduleName;
    @Schema(description = "模版ID")
    @Column(columnDefinition = "bigint comment '模版ID'")
    private Long templateId;
    /**
     * 临时字段 - 用于接收审批人名称等关联查询结果
     */
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractTemplate.java
New file
@@ -0,0 +1,31 @@
package com.by4cloud.platformx.business.entity;
import com.by4cloud.platformx.common.data.mybatis.BaseModel;
import com.fasterxml.jackson.annotation.JsonFormat;
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年4月29日 10:46:07
 * syt
 */
@Data
@Entity//加了才能自动生成表
@Table(appliesTo="contract_template",comment = "合同模版")//给表加注释
@jakarta.persistence.Table(name = "contract_template")//数据库创建的表明
public class ContractTemplate extends BaseModel<ContractTemplate> {
    @Schema(description = "模版名称")
    @Column(columnDefinition = "VARCHAR(64) comment '模版名称'")
    private String templateName;
    @Schema(description = "模版路径")
    @Column(columnDefinition="VARCHAR(255) comment '模版路径'")
    private String templatePath;
}
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractDetailVo.java
@@ -54,13 +54,16 @@
    @Schema(description = "签署日期")
    private String signDate;
    @Schema(description = "交付周期")
    private Integer deliveryCycle;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
    @Schema(description = "生效日期")
    private String effectiveDate;
    @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 = "到期日期")
    private String expirationDate;
@@ -70,6 +73,9 @@
    @Schema(description = "备注")
    private String remark;
    @Schema(description = "模版ID")
    private Long templateId;
    private List<ContractPaymentSchedule> contractPaymentSchedule;
    private List<ContractSubjectMatter> contractSubjectMatter;
platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/ContractPaymentScheduleVo.java
@@ -42,6 +42,11 @@
    @Schema(description = "收款状态(0-未收款 1-部分收款 2-已收款 3-逾期)")
    private Integer paymentStatus;
    private List<ScheduleProcessVo> processVoList;
    @Schema(description = "履约时间")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date processDate;
    @Schema(description = "约定天数")
    private Integer agreedDays;
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractController.java
@@ -2,6 +2,7 @@
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -56,6 +57,7 @@
        LambdaQueryWrapper<Contract> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(contract.getContractName()),Contract::getContractName,contract.getContractName());
        wrapper.like(StringUtils.isNotBlank(contract.getPartyA()),Contract::getPartyA,contract.getPartyA());
        wrapper.eq(ObjUtil.isNotNull(contract.getContractStatus()),Contract::getContractStatus,contract.getContractStatus());
        wrapper.orderByDesc(BaseModel::getCreateTime);
        return R.ok(contractService.pageByScope(page, wrapper));
    }
@@ -127,15 +129,14 @@
    }
    /**
     * 通过id合同生效
     * 启动审核流程
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id合同生效" , description = "通过id合同生效" )
    @GetMapping("/takeEffect/{id}" )
    @PreAuthorize("@pms.hasPermission('business_contract_effect')" )
    public R takeEffect(@PathVariable("id" ) Long id) {
        return R.ok(contractService.takeEffect(id));
    @Operation(summary = "通过id启动审核流程" , description = "通过id合同生效" )
    @GetMapping("/startApproval/{id}" )
    public R startApproval(@PathVariable("id" ) Long id) {
        return contractService.startApproval(id);
    }
@@ -148,4 +149,6 @@
    public R genCurrentOverdue() {
        return contractService.genCurrentOverdue();
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractTemplateController.java
New file
@@ -0,0 +1,127 @@
package com.by4cloud.platformx.business.controller;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.log.annotation.SysLog;
import com.by4cloud.platformx.business.entity.ContractTemplate;
import com.by4cloud.platformx.business.service.ContractTemplateService;
import org.springframework.security.access.prepost.PreAuthorize;
import com.by4cloud.platformx.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
 * 合同模版
 *
 * @author syt
 * @date 2026-05-15 14:13:59
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/contractTemplate" )
@Tag(description = "contractTemplate" , name = "合同模版管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class ContractTemplateController {
    private final  ContractTemplateService contractTemplateService;
    /**
     * 分页查询
     * @param page 分页对象
     * @param contractTemplate 合同模版
     * @return
     */
    @Operation(summary = "分页查询" , description = "分页查询" )
    @GetMapping("/page" )
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_view')" )
    public R getContractTemplatePage(@ParameterObject Page page, @ParameterObject ContractTemplate contractTemplate) {
        LambdaQueryWrapper<ContractTemplate> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(StrUtil.isNotBlank(contractTemplate.getTemplateName()),ContractTemplate::getTemplateName,contractTemplate.getTemplateName());
        wrapper.orderByDesc(ContractTemplate::getCreateTime);
        return R.ok(contractTemplateService.pageByScope(page, wrapper));
    }
    /**
     * 通过id查询合同模版
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id查询" , description = "通过id查询" )
    @GetMapping("/{id}" )
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_view')" )
    public R getById(@PathVariable("id" ) Long id) {
        return R.ok(contractTemplateService.getById(id));
    }
    /**
     * 新增合同模版
     * @param contractTemplate 合同模版
     * @return R
     */
    @Operation(summary = "新增合同模版" , description = "新增合同模版" )
    @SysLog("新增合同模版" )
    @PostMapping
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_add')" )
    public R save(@RequestBody ContractTemplate contractTemplate) {
        return R.ok(contractTemplateService.save(contractTemplate));
    }
    /**
     * 修改合同模版
     * @param contractTemplate 合同模版
     * @return R
     */
    @Operation(summary = "修改合同模版" , description = "修改合同模版" )
    @SysLog("修改合同模版" )
    @PutMapping
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_edit')" )
    public R updateById(@RequestBody ContractTemplate contractTemplate) {
        return R.ok(contractTemplateService.updateById(contractTemplate));
    }
    /**
     * 通过id删除合同模版
     * @param ids id列表
     * @return R
     */
    @Operation(summary = "通过id删除合同模版" , description = "通过id删除合同模版" )
    @SysLog("通过id删除合同模版" )
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_del')" )
    public R removeById(@RequestBody Long[] ids) {
        return R.ok(contractTemplateService.removeBatchByIds(CollUtil.toList(ids)));
    }
    /**
     * 导出excel 表格
     * @param contractTemplate 查询条件
        * @param ids 导出指定ID
     * @return excel 文件流
     */
    @ResponseExcel
    @GetMapping("/export")
    @PreAuthorize("@pms.hasPermission('business_contractTemplate_export')" )
    public List<ContractTemplate> export(ContractTemplate contractTemplate,Long[] ids) {
        return contractTemplateService.list(Wrappers.lambdaQuery(contractTemplate).in(ArrayUtil.isNotEmpty(ids), ContractTemplate::getId, ids));
    }
    @GetMapping("/listAll" )
    public R listAll() {
        return R.ok(contractTemplateService.listByScope(Wrappers.<ContractTemplate>lambdaQuery().orderByDesc(ContractTemplate::getCreateTime)));
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/CurrentOverdueController.java
@@ -53,6 +53,7 @@
        LambdaQueryWrapper<CurrentOverdue> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StrUtil.isNotBlank(currentOverdue.getBusGuestName()),CurrentOverdue::getBusGuestName,currentOverdue.getBusGuestName());
        wrapper.like(StrUtil.isNotBlank(currentOverdue.getContractName()),CurrentOverdue::getContractName,currentOverdue.getContractName());
        wrapper.like(StrUtil.isNotBlank(currentOverdue.getScheduleName()),CurrentOverdue::getScheduleName,currentOverdue.getScheduleName());
        wrapper.orderByDesc(CurrentOverdue::getCreateTime);
        return R.ok(currentOverdueService.pageByScope(page, wrapper));
    }
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/FlowCallBackController.java
New file
@@ -0,0 +1,50 @@
package com.by4cloud.platformx.business.controller;
import com.by4cloud.platformx.business.constant.FlowNameEnum;
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.flow.task.dto.ProcessInstanceParamDto;
import com.by4cloud.platformx.flow.task.dto.ProcessNodeRecordParamDto;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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 xfei
 * @date 2025/5/12 17:07
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/flowCallBack" )
@Slf4j
@Tag(description = "flowCallBack" , name = "流程回调" )
public class FlowCallBackController {
    private final ContractService contractService;
    /**
     * 开始节点事件
     * @param recordParamDto
     * @return
     */
    @PostMapping("/startNodeEvent")
    public void startNodeEvent(@RequestBody ProcessNodeRecordParamDto recordParamDto){
    }
    /**
     * 任务结束事件
     * @param processInstanceParamDto
     * @return
     */
    @PostMapping("/endProcess")
    public void endProcessEvent(@RequestBody ProcessInstanceParamDto processInstanceParamDto) {
        if (processInstanceParamDto.getFlowName().equals(FlowNameEnum.合同审批.getName())) {
            contractService.startApproval(Long.valueOf(processInstanceParamDto.getParamMap().get("id")+""));
        }
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/HistoryOverdueController.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.by4cloud.platformx.business.entity.CurrentOverdue;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.log.annotation.SysLog;
import com.by4cloud.platformx.business.entity.HistoryOverdue;
@@ -51,6 +52,7 @@
        LambdaQueryWrapper<HistoryOverdue> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StrUtil.isNotBlank(historyOverdue.getBusGuestName()),HistoryOverdue::getBusGuestName,historyOverdue.getBusGuestName());
        wrapper.like(StrUtil.isNotBlank(historyOverdue.getContractName()),HistoryOverdue::getContractName,historyOverdue.getContractName());
        wrapper.like(StrUtil.isNotBlank(historyOverdue.getScheduleName()), HistoryOverdue::getScheduleName,historyOverdue.getScheduleName());
        wrapper.orderByDesc(HistoryOverdue::getCreateTime);
        return R.ok(historyOverdueService.pageByScope(page, wrapper));
    }
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/ContractTemplateMapper.java
New file
@@ -0,0 +1,11 @@
package com.by4cloud.platformx.business.mapper;
import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper;
import com.by4cloud.platformx.business.entity.ContractTemplate;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ContractTemplateMapper extends PlatformxBaseMapper<ContractTemplate> {
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractService.java
@@ -19,7 +19,7 @@
    ContractDetailVo detail(Long id);
    Boolean takeEffect(Long id);
    R startApproval(Long id);
    R genCurrentOverdue();
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractTemplateService.java
New file
@@ -0,0 +1,9 @@
package com.by4cloud.platformx.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.by4cloud.platformx.business.entity.ContractTemplate;
import com.by4cloud.platformx.common.data.mybatis.IIService;
public interface ContractTemplateService extends IIService<ContractTemplate> {
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractPaymentScheduleProcessServiceImpl.java
@@ -8,14 +8,8 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.business.dto.ContractPaymentScheduleProcessAddDTO;
import com.by4cloud.platformx.business.entity.Contract;
import com.by4cloud.platformx.business.entity.ContractPaymentSchedule;
import com.by4cloud.platformx.business.entity.ContractPaymentScheduleProcess;
import com.by4cloud.platformx.business.entity.PaymentConfirm;
import com.by4cloud.platformx.business.mapper.ContractMapper;
import com.by4cloud.platformx.business.mapper.ContractPaymentScheduleMapper;
import com.by4cloud.platformx.business.mapper.ContractPaymentScheduleProcessMapper;
import com.by4cloud.platformx.business.mapper.PaymentConfirmMapper;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.ContractPaymentScheduleProcessService;
import com.by4cloud.platformx.business.vo.ContractPaymentScheduleVo;
import com.by4cloud.platformx.business.vo.ScheduleProcessVo;
@@ -41,6 +35,7 @@
    private final ContractPaymentScheduleMapper contractPaymentScheduleMapper;
    private final ContractPaymentScheduleProcessMapper processMapper;
    private final ContractMapper contractMapper;
    private final ContractSubjectMatterMapper subjectMatterMapper;
    private final PaymentConfirmMapper paymentConfirmMapper;
    @Override
@@ -51,6 +46,13 @@
        }
        //合同
        Contract contract = contractMapper.selectById(schedule.getContractId());
        List<ContractSubjectMatter> subjectMatterList = subjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery().eq(ContractSubjectMatter::getContractId,contract.getId()));
        if (ArrayUtil.isEmpty(subjectMatterList.toArray())){
            return R.failed("该合同标的物异常,请联系技术人员");
        }
        if (!subjectMatterList.stream().allMatch(item->item.getDeliveryStatus()==2)){
            return R.failed("出库数量小于当前合同标的物数量,无法进行当前操作");
        }
        //新增当前阶段应收
        PaymentConfirm currentConfim = new PaymentConfirm();
        currentConfim.setBusinessType(schedule.getStageName()+"应收");
@@ -88,7 +90,7 @@
        ContractPaymentSchedule beforeSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                .lt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder()).orderByDesc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
        if (ObjUtil.isNotNull(beforeSchedule)){
            beforeSchedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getProcessDate(),beforeSchedule.getAgreedDays()));
            beforeSchedule.setEffectiveEndDate(schedule.getEffectiveDate());
            contractPaymentScheduleMapper.updateById(beforeSchedule);
            //之前阶段是否收款完成
//            if (beforeSchedule.getPaymentStatus()!=2){
@@ -166,6 +168,14 @@
            //更新合同下个阶段
            contract.setNextScheduleName("无");
            contractMapper.updateById(contract);
            //当前为合同最后阶段
            PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId())
                    .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
            if (lastNewConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>=0){
                //有预付且超过应收 关闭合同状态
                contract.setContractStatus(3);
                contractMapper.updateById(contract);
            }
        }
        return R.ok();
    }
@@ -176,20 +186,13 @@
                .select(ContractPaymentSchedule::getId,ContractPaymentSchedule::getStageName,ContractPaymentSchedule::getEffectiveDate,
                        ContractPaymentSchedule::getPlannedAmount,ContractPaymentSchedule::getPlannedAmount,
                        ContractPaymentSchedule::getEffectiveEndDate,ContractPaymentSchedule::getPaymentDate,
                        ContractPaymentSchedule::getPaymentStatus,ContractPaymentSchedule::getActualAmount)
                        ContractPaymentSchedule::getPaymentStatus,ContractPaymentSchedule::getActualAmount,
                        ContractPaymentSchedule::getAgreedDays)
                .select(ContractPaymentScheduleProcess::getProcessDate)
                .leftJoin(ContractPaymentScheduleProcess.class,ContractPaymentScheduleProcess::getScheduleId,ContractPaymentSchedule::getId)
                .eq(ContractPaymentSchedule::getContractId,id)
                .orderByAsc(ContractPaymentSchedule::getCreateTime);
        List<ContractPaymentScheduleVo> scheduleVoList = contractPaymentScheduleMapper.selectJoinList(ContractPaymentScheduleVo.class,wrapper);
        if (ArrayUtil.isEmpty(scheduleVoList.toArray())){
            scheduleVoList.stream().forEach(contractPaymentScheduleVo -> {
                List<ContractPaymentScheduleProcess> paymentScheduleProcessList = processMapper.selectList(Wrappers.<ContractPaymentScheduleProcess>lambdaQuery()
                        .eq(ContractPaymentScheduleProcess::getContractId,contractPaymentScheduleVo.getId())
                        .orderByAsc(ContractPaymentScheduleProcess::getCreateTime));
                if (ArrayUtil.isNotEmpty(paymentScheduleProcessList.toArray())){
                    contractPaymentScheduleVo.setProcessVoList(BeanUtil.copyToList(paymentScheduleProcessList, ScheduleProcessVo.class));
                }
            });
        }
        return R.ok(scheduleVoList);
    }
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java
@@ -7,6 +7,8 @@
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.business.api.feign.RemoteFlowProcessService;
import com.by4cloud.platformx.business.constant.FlowNameEnum;
import com.by4cloud.platformx.business.dto.ContractAddDTO;
import com.by4cloud.platformx.business.dto.ContractUpdateDTO;
import com.by4cloud.platformx.business.entity.*;
@@ -16,6 +18,8 @@
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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -23,6 +27,7 @@
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -39,6 +44,7 @@
    private final ContractPaymentScheduleProcessMapper contractPaymentScheduleProcessMapper;
    private final PaymentConfirmMapper paymentConfirmMapper;
    private final CurrentOverdueMapper currentOverdueMapper;
    private final RemoteFlowProcessService remoteFlowProcessService;
    @Override
    public R add(ContractAddDTO addDTO) {
@@ -114,6 +120,14 @@
        }
        Contract contract = BeanUtil.copyProperties(updateDTO,Contract.class);
        contract.setContractNo(ContractNumberGenerator.generateContractNumber());
        contract.setBillingStatus("0");
        contract.setErpPushFlag("0");
        List<Contract> contracts;
        contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,contract.getContractNo()));
        while (ArrayUtil.isNotEmpty(contracts.toArray())){
            contract.setContractNo(ContractNumberGenerator.generateContractNumber());
            contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,contract.getContractNo()));
        }
        baseMapper.updateById(contract);
        if (ArrayUtil.isNotEmpty(updateDTO.getContractSubjectMatter())){
@@ -135,12 +149,20 @@
            AtomicInteger index = new AtomicInteger(1);
            updateDTO.getContractPaymentSchedule().stream().forEach(contractPaymentScheduleAddDTO -> {
                int currentIndex = index.getAndIncrement();
                ContractPaymentSchedule subjectMatter = BeanUtil.copyProperties(contractPaymentScheduleAddDTO, ContractPaymentSchedule.class);
                subjectMatter.setContractId(contract.getId());
                subjectMatter.setContractName(contract.getContractName());
                subjectMatter.setPlannedAmount(contract.getAmount().multiply(subjectMatter.getPaymentRatio().divide(new BigDecimal("100"))));
                subjectMatter.setStageOrder(currentIndex);
                contractPaymentScheduleMapper.insert(subjectMatter);
                ContractPaymentSchedule schedule = BeanUtil.copyProperties(contractPaymentScheduleAddDTO, ContractPaymentSchedule.class);
                schedule.setContractId(contract.getId());
                schedule.setContractName(contract.getContractName());
                schedule.setPlannedAmount(contract.getAmount().multiply(schedule.getPaymentRatio().divide(new BigDecimal("100"))));
                schedule.setStageOrder(currentIndex);
                contractPaymentScheduleMapper.insert(schedule);
                if (contractPaymentScheduleAddDTO.getStageName().equals("货到签收")){
                    contract.setArrivalScheduleId(schedule.getId());
                    baseMapper.updateById(contract);
                }
                if (contractPaymentScheduleAddDTO.getStageName().equals("调试完成或验收")){
                    contract.setAcceptScheduleId(schedule.getId());
                    baseMapper.updateById(contract);
                }
            });
        }
@@ -160,7 +182,23 @@
    }
    @Override
    public Boolean takeEffect(Long id) {
    public R startApproval(Long id) {
        Contract contract = baseMapper.selectById(id);
        //启动流程
        ProcessInstanceParamDto dto = new ProcessInstanceParamDto();
        Map<String, Object> map = BeanUtil.beanToMap(contract);
        dto.setParamMap(map);
        dto.setFlowName(FlowNameEnum.合同审批.name());
        R r1 = remoteFlowProcessService.startProcessInstance(dto);
        if (r1.getCode() == 1) {
            return R.failed("流程启动失败");
        }
        contract.setContractStatus(2);
        baseMapper.updateById(contract);
        return R.ok();
    }
    public void takeEffect(Long id) {
        Contract contract = baseMapper.selectById(id);
        contract.setContractStatus(1);
        baseMapper.updateById(contract);
@@ -181,6 +219,13 @@
            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()));
            paymentConfirmMapper.insert(paymentConfirm);
            //新增合同履约记录
            ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess();
@@ -190,6 +235,49 @@
            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 (newConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>=0){
                //有预付且超过应收 关闭合同状态
                contract.setContractStatus(3);
                baseMapper.updateById(contract);
            }
        }else if (fitstSchedule.getStageName().equals("发货前")) {
            //更新合同下个阶段
            contract.setNextScheduleName("无");
            baseMapper.updateById(contract);
        }else if (fitstSchedule.getStageName().equals("货到签收")) {
            //更新合同下个阶段
            contract.setNextScheduleName("货到签收");
            baseMapper.updateById(contract);
        }else if (fitstSchedule.getStageName().equals("调试完成或验收")) {
            //更新合同下个阶段
            contract.setNextScheduleName("调试完成或验收");
            baseMapper.updateById(contract);
        }else {
            //新增应收
            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()));
            paymentConfirmMapper.insert(paymentConfirm);
        }
        //查询是否有后续阶段
        List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
@@ -204,7 +292,7 @@
                endSchedule.setEffectiveEndDate(contract.getExpirationDate());
                contractPaymentScheduleMapper.updateById(endSchedule);
                //第一阶段生效时间
                fitstSchedule.setEffectiveDate(DateUtil.offsetDay(new Date(),fitstSchedule.getAgreedDays()));
                fitstSchedule.setEffectiveDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
                fitstSchedule.setEffectiveEndDate(endSchedule.getEffectiveDate());
                contractPaymentScheduleMapper.updateById(fitstSchedule);
@@ -235,18 +323,19 @@
            baseMapper.updateById(contract);
        }
        if(ArrayUtil.isNotEmpty(afterSchedule.toArray())&&afterSchedule.size()>1){
            //第一阶段生效时间
            fitstSchedule.setEffectiveDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
            contractPaymentScheduleMapper.updateById(fitstSchedule);
            //更新合同下个阶段
            contract.setNextScheduleName(afterSchedule.get(0).getStageName());
            baseMapper.updateById(contract);
        }
        //只有当前合同签字阶段
        if(ArrayUtil.isEmpty(afterSchedule.toArray())){
            fitstSchedule.setEffectiveDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays()));
            fitstSchedule.setEffectiveEndDate(contract.getExpirationDate());
            contractPaymentScheduleMapper.updateById(fitstSchedule);
            //更新合同下个阶段
            contract.setNextScheduleName("无");
            baseMapper.updateById(contract);
        }
        return Boolean.TRUE;
    }
    @Override
@@ -281,6 +370,7 @@
                PaymentConfirm oiverdueConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getScheduleId, contractPaymentSchedule.getId())
                        .eq(PaymentConfirm::getBusinessType, "应收超期"));
                if (ObjUtil.isNull(oiverdueConfirm)) {
                    overdueConfirm.setCompId(contractPaymentSchedule.getCompId());
                    paymentConfirmMapper.insert(overdueConfirm);
                }
                //当前逾期
@@ -299,6 +389,7 @@
                CurrentOverdue overdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getContractId,currentOverdue.getContractId())
                        .eq(CurrentOverdue::getScheduleId,currentOverdue.getScheduleId()).last("limit 1"));
                if (ObjUtil.isNull(overdue)){
                    currentOverdue.setCompId(contractPaymentSchedule.getCompId());
                    currentOverdueMapper.insert(currentOverdue);
                }else {
                    overdue.setOverdueDuration(BigDecimal.valueOf(DateUtil.betweenDay(contractPaymentSchedule.getEffectiveEndDate(),new Date(),true)));
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractTemplateServiceImpl.java
New file
@@ -0,0 +1,16 @@
package com.by4cloud.platformx.business.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.business.entity.ContractTemplate;
import com.by4cloud.platformx.business.mapper.ContractTemplateMapper;
import com.by4cloud.platformx.business.service.ContractTemplateService;
import org.springframework.stereotype.Service;
/**
 * 合同模版
 *
 * @author syt
 * @date 2026-05-15 14:13:59
 */
@Service
public class ContractTemplateServiceImpl extends ServiceImpl<ContractTemplateMapper, ContractTemplate> implements ContractTemplateService {
}
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/OutBoundServiceImpl.java
@@ -19,10 +19,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -50,7 +47,7 @@
        MPJLambdaWrapper<ContractSubjectMatter> wrapper = new MPJLambdaWrapper<ContractSubjectMatter>()
                .selectAll(ContractSubjectMatter.class)
                .ne(ContractSubjectMatter::getDeliveryStatus, 2)
                .in(ContractSubjectMatter::getMaterialCode,addDTO.getSubjectMatterList().stream().map(item->item.getSubjectMatterCode()).collect(Collectors.toList()))
                .in(ContractSubjectMatter::getMaterialCode, addDTO.getSubjectMatterList().stream().map(item -> item.getSubjectMatterCode()).collect(Collectors.toList()))
                .exists(Contract.class, contractQuery ->
                        contractQuery.select(ContractSubjectMatter::getId)
                                .eq(Contract::getId, ContractSubjectMatter::getContractId)
@@ -78,64 +75,67 @@
            return R.failed("出库数量超出合同订单数量");
        }
        //当前入库标的物
        List<ContractSubjectMatter> currentOutList = new ArrayList<>();
        Map<Long, Object> currentOutMap = new HashMap<>();
        //出库
        addDTO.getSubjectMatterList().stream().forEach(outSubjectMatterAddDTO -> {
            BigDecimal remainNum = outSubjectMatterAddDTO.getOutBoundNum();
            for (ContractSubjectMatter subjectMatter : subjectMatterList) {
                Contract contract = contractMapper.selectById(subjectMatter.getContractId());
                if (subjectMatter.getDeliveredQuantity().compareTo(new BigDecimal("0")) > 0) {
                    remainNum = remainNum.subtract(subjectMatter.getRemainingQuantity());
                    //部分交付状态下 全部出库
                    if (remainNum.compareTo(new BigDecimal("0")) >= 0) {
                        BigDecimal currentOut = subjectMatter.getRemainingQuantity();
                        subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity());
                        subjectMatter.setRemainingQuantity(new BigDecimal("0"));
                        subjectMatter.setActualDeliveryDate(DateUtil.today());
                        subjectMatter.setDeliveryStatus(2);
                        subjectMatter.setLastDeliveredQuantity(currentOut);
                        contractSubjectMatterMapper.updateById(subjectMatter);
                        currentOutList.add(subjectMatter);
                        //新增合同出库历史
                        saveContractOutBound(contract,addDTO,subjectMatter);
                    } else {
                        BigDecimal currentOut = remainNum.add(subjectMatter.getRemainingQuantity());
                        subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
                        subjectMatter.setRemainingQuantity(subjectMatter.getRemainingQuantity().subtract(currentOut));
                        subjectMatter.setActualDeliveryDate(DateUtil.today());
                        subjectMatter.setDeliveryStatus(1);
                        subjectMatter.setLastDeliveredQuantity(currentOut);
                        contractSubjectMatterMapper.updateById(subjectMatter);
                        currentOutList.add(subjectMatter);
                        //新增合同出库历史
                        saveContractOutBound(contract,addDTO,subjectMatter);
                        break;
                    }
                if (outSubjectMatterAddDTO.getSubjectMatterCode().equals(subjectMatter.getMaterialCode())) {
                    Contract contract = contractMapper.selectById(subjectMatter.getContractId());
                    if (subjectMatter.getDeliveredQuantity().compareTo(new BigDecimal("0")) > 0) {
                        remainNum = remainNum.subtract(subjectMatter.getRemainingQuantity());
                        //部分交付状态下 全部出库
                        if (remainNum.compareTo(new BigDecimal("0")) >= 0) {
                            BigDecimal currentOut = subjectMatter.getRemainingQuantity();
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity());
                            subjectMatter.setRemainingQuantity(new BigDecimal("0"));
                            subjectMatter.setActualDeliveryDate(DateUtil.today());
                            subjectMatter.setDeliveryStatus(2);
                            subjectMatter.setLastDeliveredQuantity(currentOut);
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                        } else {
                            BigDecimal currentOut = remainNum.add(subjectMatter.getRemainingQuantity());
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
                            subjectMatter.setRemainingQuantity(subjectMatter.getRemainingQuantity().subtract(currentOut));
                            subjectMatter.setActualDeliveryDate(DateUtil.today());
                            subjectMatter.setDeliveryStatus(1);
                            subjectMatter.setLastDeliveredQuantity(currentOut);
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            break;
                        }
                } else {
                    //未交付状态下
                    remainNum = remainNum.subtract(subjectMatter.getQuantity());
                    if (remainNum.compareTo(new BigDecimal("0")) >= 0) {
                        subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity());
                        subjectMatter.setRemainingQuantity(new BigDecimal("0"));
                        subjectMatter.setActualDeliveryDate(DateUtil.today());
                        subjectMatter.setDeliveryStatus(2);
                        subjectMatter.setLastDeliveredQuantity(subjectMatter.getQuantity());
                        contractSubjectMatterMapper.updateById(subjectMatter);
                        currentOutList.add(subjectMatter);
                        //新增合同出库历史
                        saveContractOutBound(contract,addDTO,subjectMatter);
                    } else {
                        BigDecimal currentOut = remainNum.add(subjectMatter.getQuantity());
                        subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
                        subjectMatter.setRemainingQuantity(remainNum.multiply(new BigDecimal("-1")));
                        subjectMatter.setActualDeliveryDate(DateUtil.today());
                        subjectMatter.setDeliveryStatus(1);
                        subjectMatter.setLastDeliveredQuantity(currentOut);
                        contractSubjectMatterMapper.updateById(subjectMatter);
                        currentOutList.add(subjectMatter);
                        //新增合同出库历史
                        saveContractOutBound(contract,addDTO,subjectMatter);
                        break;
                        //未交付状态下
                        remainNum = remainNum.subtract(subjectMatter.getQuantity());
                        if (remainNum.compareTo(new BigDecimal("0")) >= 0) {
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity());
                            subjectMatter.setRemainingQuantity(new BigDecimal("0"));
                            subjectMatter.setActualDeliveryDate(DateUtil.today());
                            subjectMatter.setDeliveryStatus(2);
                            subjectMatter.setLastDeliveredQuantity(subjectMatter.getQuantity());
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                        } else {
                            BigDecimal currentOut = remainNum.add(subjectMatter.getQuantity());
                            subjectMatter.setDeliveredQuantity(subjectMatter.getQuantity().add(remainNum));
                            subjectMatter.setRemainingQuantity(remainNum.multiply(new BigDecimal("-1")));
                            subjectMatter.setActualDeliveryDate(DateUtil.today());
                            subjectMatter.setDeliveryStatus(1);
                            subjectMatter.setLastDeliveredQuantity(currentOut);
                            contractSubjectMatterMapper.updateById(subjectMatter);
                            currentOutMap.put(subjectMatter.getContractId(), subjectMatter);
                            //新增合同出库历史
                            saveContractOutBound(contract, addDTO, subjectMatter);
                            break;
                        }
                    }
                }
            }
@@ -147,32 +147,32 @@
        });
        //出库应收款明细
        if (ArrayUtil.isNotEmpty(currentOutList.toArray())) {
            //根据合同id拆分应收明细
            Map<Long, List<ContractSubjectMatter>> conSubMatMap = currentOutList.stream().collect(Collectors.groupingBy(ContractSubjectMatter::getContractId));
            conSubMatMap.forEach((key, value) -> {
        if (ArrayUtil.isNotEmpty(currentOutMap.keySet())) {
            for (Long contractId : currentOutMap.keySet()) {
                //当前出库合同出库标的物
                List<ContractSubjectMatter> contractSubjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery()
                        .eq(ContractSubjectMatter::getContractId, contractId).ne(ContractSubjectMatter::getDeliveryStatus, 0));
                //查询合同是否有出库阶段
                ContractPaymentSchedule schedule = scheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, key)
                ContractPaymentSchedule schedule = scheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contractId)
                        .eq(ContractPaymentSchedule::getStageName, "发货前"));
                //当前出库金额
                BigDecimal outPirce = value.stream()
                        .filter(item -> item.getLastDeliveredQuantity() != null && item.getUnitPrice() != null)
                        .map(item ->(item.getDeliveryStatus()==1?item.getDeliveredQuantity():item.getQuantity()).multiply(item.getUnitPrice()))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                //合同金额
                Contract contract = contractMapper.selectById(key);
                //出库是否完成
                if (outPirce.compareTo(contract.getAmount())<0){
                    contract.setBillingStatus("1");
                    contractMapper.updateById(contract);
                }
                if (outPirce.compareTo(contract.getAmount())==0){
                    contract.setBillingStatus("2");
                    contractMapper.updateById(contract);
                }
                //存在出库阶段
                if (ObjUtil.isNotNull(schedule)) {
                    //按出库资金比例 计算发货前应收更新资金明细
                    //当前出库金额
                    BigDecimal outPirce = contractSubjectMatterList.stream()
                            .map(item -> (item.getDeliveryStatus() == 1 ? item.getDeliveredQuantity().multiply(item.getUnitPrice()) : item.getQuantity().multiply(item.getUnitPrice())))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    //合同金额
                    Contract contract = contractMapper.selectById(contractId);
                    //出库是否完成
                    if (outPirce.compareTo(contract.getAmount()) < 0) {
                        contract.setBillingStatus("1");
                        contractMapper.updateById(contract);
                    }
                    if (outPirce.compareTo(contract.getAmount()) == 0) {
                        contract.setBillingStatus("2");
                        contractMapper.updateById(contract);
                    }
                    //计算发货前应收更新资金明细
                    PaymentConfirm paymentConfirm = new PaymentConfirm();
                    paymentConfirm.setBusinessType("发货前应收");
                    paymentConfirm.setBusGuestId(contract.getPartyAId());
@@ -183,53 +183,74 @@
                    paymentConfirm.setScheduleId(schedule.getId());
                    paymentConfirm.setScheduleName(schedule.getStageName());
                    paymentConfirm.setConfirmTime(addDTO.getOutBoundTime());
                    //按出库资金比例 计算发货前应收
                    paymentConfirm.setTransationAmount(outPirce.divide(contract.getAmount(), 10, RoundingMode.HALF_UP).multiply(schedule.getPlannedAmount()));
                    paymentConfirm.setReceivableAmount(paymentConfirm.getTransationAmount());
                    paymentConfirm.setTotalAmount(paymentConfirm.getTransationAmount().multiply(new BigDecimal("-1")));
                    //最近应收
                    PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                    if (ObjUtil.isNotNull(lastConfirm)) {
                        paymentConfirm.setTotalAmount(paymentConfirm.getTotalAmount().add(lastConfirm.getTotalAmount()));
                        paymentConfirmMapper.insert(paymentConfirm);
                        //已存在发货应收
                        if (StrUtil.equals(lastConfirm.getBusinessType(), paymentConfirm.getBusinessType())) {
                            //查询之前所有发货前应收
                            List<PaymentConfirm> fhConfirmList = paymentConfirmMapper.selectList(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
                                    .eq(PaymentConfirm::getScheduleId,schedule.getId()).orderByDesc(PaymentConfirm::getCreateTime));
                            BigDecimal fhTotalAmount = fhConfirmList.stream().map(item->item.getTransationAmount()).reduce(BigDecimal.ZERO,BigDecimal::add);
                            //本次发货前应收 出库总额 - 所有发货前应收
                            paymentConfirm.setTransationAmount(paymentConfirm.getTransationAmount().subtract(fhTotalAmount));
                            paymentConfirm.setReceivableAmount(paymentConfirm.getTransationAmount());
                            paymentConfirm.setTotalAmount(lastConfirm.getTotalAmount().subtract(paymentConfirm.getTransationAmount()));
                            paymentConfirmMapper.insert(paymentConfirm);
                        } else {
                            //不存在发货应收 出库总额
                            paymentConfirm.setTotalAmount(lastConfirm.getTotalAmount().subtract(paymentConfirm.getTransationAmount()));
                            paymentConfirmMapper.insert(paymentConfirm);
                        }
                    } else {
                        //无之前阶段应收
                        paymentConfirm.setTotalAmount(paymentConfirm.getTransationAmount().multiply(new BigDecimal("-1")));
                        paymentConfirmMapper.insert(paymentConfirm);
                    }
                    //更新发货前收款生效时间
                    if (ObjUtil.isNull(schedule.getEffectiveDate())){
                        schedule.setEffectiveDate(DateUtil.offsetDay(addDTO.getOutBoundTime(),schedule.getAgreedDays()));
                    if (ObjUtil.isNull(schedule.getEffectiveDate())) {
                        schedule.setEffectiveDate(DateUtil.offsetDay(addDTO.getOutBoundTime(), schedule.getAgreedDays()));
                        //查询是否有后续阶段
                        List<ContractPaymentSchedule> afterSchedule = scheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, key)
                        List<ContractPaymentSchedule> afterSchedule = scheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contractId)
                                .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder()));
                        if (ArrayUtil.isEmpty(afterSchedule.toArray())){
                        if (ArrayUtil.isEmpty(afterSchedule.toArray())) {
                            schedule.setEffectiveEndDate(contract.getExpirationDate());
                        }
                        scheduleMapper.updateById(schedule);
                        //查询是否有之前阶段
                        ContractPaymentSchedule beforeSchedule = scheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                                .lt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder()).orderByDesc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
                        if (ObjUtil.isNotNull(beforeSchedule)){
                            beforeSchedule.setEffectiveEndDate(DateUtil.offsetDay(addDTO.getOutBoundTime(),beforeSchedule.getAgreedDays()));
                        if (ObjUtil.isNotNull(beforeSchedule)) {
                            beforeSchedule.setEffectiveEndDate(schedule.getEffectiveDate());
                            scheduleMapper.updateById(beforeSchedule);
                        }
                        //更新履约
                        ContractPaymentScheduleProcess contractPaymentScheduleProcess = new ContractPaymentScheduleProcess();
                        contractPaymentScheduleProcess.setContractId(schedule.getContractId());
                        contractPaymentScheduleProcess.setContractName(schedule.getContractName());
                        contractPaymentScheduleProcess.setScheduleId(schedule.getId());
                        contractPaymentScheduleProcess.setScheduleName(schedule.getStageName());
                        contractPaymentScheduleProcess.setProcessDate(addDTO.getOutBoundTime());
                        scheduleProcessMapper.insert(contractPaymentScheduleProcess);
                    }
                    //更新履约
                    ContractPaymentScheduleProcess contractPaymentScheduleProcess = new ContractPaymentScheduleProcess();
                    contractPaymentScheduleProcess.setContractId(schedule.getContractId());
                    contractPaymentScheduleProcess.setContractName(schedule.getContractName());
                    contractPaymentScheduleProcess.setScheduleId(schedule.getId());
                    contractPaymentScheduleProcess.setScheduleName(schedule.getStageName());
                    contractPaymentScheduleProcess.setProcessDate(addDTO.getOutBoundTime());
                    scheduleProcessMapper.insert(contractPaymentScheduleProcess);
                    //查询是否有后续阶段
                    List<ContractPaymentSchedule> afterSchedule = scheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
                            .eq(ContractPaymentSchedule::getContractId, schedule.getContractId())
                            .gt(ContractPaymentSchedule::getStageOrder, schedule.getStageOrder())
                            .orderByAsc(ContractPaymentSchedule::getCreateTime));
                    if (ArrayUtil.isNotEmpty(afterSchedule.toArray())&&afterSchedule.size()==1){
                    if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() == 1) {
                        //最后阶段生效时间
                        ContractPaymentSchedule endSchedule = afterSchedule.get(0);
                        if (StrUtil.equals(endSchedule.getStageName(),"质保金")) {
                        if (StrUtil.equals(endSchedule.getStageName(), "质保金")) {
                            endSchedule.setEffectiveDate(DateUtil.offsetDay(addDTO.getOutBoundTime(), endSchedule.getAgreedDays()));
                            endSchedule.setEffectiveEndDate(contract.getExpirationDate());
                            scheduleMapper.updateById(endSchedule);
@@ -263,20 +284,28 @@
                        contract.setNextScheduleName(endSchedule.getStageName());
                        contractMapper.updateById(contract);
                    }
                    if(ArrayUtil.isNotEmpty(afterSchedule.toArray())&&afterSchedule.size()>1){
                    if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() > 1) {
                        //更新合同下个阶段
                        contract.setNextScheduleName(afterSchedule.get(0).getStageName());
                        contractMapper.updateById(contract);
                    }
                    if(ArrayUtil.isEmpty(afterSchedule.toArray())){
                    if (ArrayUtil.isEmpty(afterSchedule.toArray())) {
                        schedule.setEffectiveEndDate(contract.getExpirationDate());
                        scheduleMapper.updateById(schedule);
                        //更新合同下个阶段
                        contract.setNextScheduleName("无");
                        contractMapper.updateById(contract);
                        //当前为合同最后阶段
                        PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId())
                                .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
                        if (lastNewConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>=0){
                            //有预付且超过应收 关闭合同状态
                            contract.setContractStatus(3);
                            contractMapper.updateById(contract);
                        }
                    }
                }
            });
            }
        }
        return R.ok();
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -98,6 +98,7 @@
            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){
@@ -112,16 +113,34 @@
                            //新增逾期历史
                            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.getPlannedAmount().subtract(schedule.getActualAmount()).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;
                    }
                }
platformx-business-finance-biz/src/main/resources/mapper/ContractTemplateMapper.xml
New file
@@ -0,0 +1,17 @@
<?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.ContractTemplateMapper">
  <resultMap id="contractOutBoundMap" type="com.by4cloud.platformx.business.entity.ContractTemplate">
        <id property="id" column="id"/>
        <result property="compId" column="comp_id"/>
        <result property="templateName" column="template_name"/>
        <result property="templatePath" column="contract_path"/>
        <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>