platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractAddDTO.java
@@ -4,10 +4,12 @@ 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; import java.math.BigDecimal; import java.util.Date; import java.util.List; @Data @@ -48,15 +50,10 @@ @Schema(description = "合同服务属性(0-产品销售 1-无形服务)") 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 = "签署日期") private String signDate; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") @JsonFormat(pattern = "yyyy-MM-dd HH:mm") @Schema(description = "生效日期") private String effectiveDate; private Date signDate; @Schema(description = "交付周期") private Integer deliveryCycle; @@ -75,6 +72,18 @@ @Schema(description = "模版ID") private Long templateId; @Schema(description = "合同分类") private String contractCategory; @Schema(description = "执行周期 1/周 2/月 3/季度 4/半年 5/年") private String execFrequency; @Schema(description = "执行次数") private Integer execTimes; @Schema(description = "执行日期后多少天生成应收") private Integer execDay; private List<ContractPaymentScheduleAddDTO> contractPaymentSchedule; private List<ContractSubjectMatterAddDTO> contractSubjectMatter; platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractSubjectMatterAddDTO.java
@@ -27,4 +27,16 @@ @Schema(description = "单价") private BigDecimal unitPrice; @Schema(description = "抄表编号") private String meterReadCode; @Schema(description = "抄表数字") private BigDecimal meterReadNum; @Schema(description = "抄表单据名称") private String meterReadAttNames; @Schema(description = "抄表单据路径") private String meterReadAttPaths; } platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/MeterReadRecordAddDTO.java
New file @@ -0,0 +1,46 @@ package com.by4cloud.platformx.business.dto; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.util.Date; @Data public class MeterReadRecordAddDTO { @Schema(description = "关联合同ID") private Long contractId; @Schema(description = "关联标的物ID") private Long matterId; @Schema(description = "合同名称") private String contractName; @Schema(description = "客商名称") private String busGuestName; @Schema(description = "客商ID") private Long busGuestId; @Schema(description = "抄表编号") private String meterReadCode; @Schema(description = "抄表数字") private BigDecimal meterReadNum; @Schema(description = "抄表时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") private Date meterReadTime; @Schema(description = "抄表单据名称") private String meterReadAttNames; @Schema(description = "抄表单据路径") private String meterReadAttPaths; } platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/MeterReadRecordUpdateDTO.java
New file @@ -0,0 +1,10 @@ package com.by4cloud.platformx.business.dto; import lombok.Data; @Data public class MeterReadRecordUpdateDTO extends MeterReadRecordAddDTO{ private Long id; } platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/Contract.java
@@ -159,7 +159,23 @@ @Column(columnDefinition = "decimal(10,2) comment '已付款金额'") private BigDecimal paidAmount; /** @Schema(description = "合同分类") @Column(columnDefinition = "VARCHAR(64) comment '合同分类 water_house 水电房屋租赁'") private String contractCategory; @Schema(description = "执行周期") @Column(columnDefinition = "char comment '执行周期 1/周 2/月 3/季度 4/半年 5/年'") private String execFrequency; @Schema(description = "执行次数") @Column(columnDefinition = "int comment '合同分类 water_house 水电房屋租赁'") private Integer execTimes; @Schema(description = "执行日期后多少天生成应收") @Column(columnDefinition = "int comment '执行日期后多少天生成应收'") private Integer execDay; /** * 临时字段 - 用于接收审批人名称等关联查询结果 */ @Transient platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractExecDate.java
New file @@ -0,0 +1,41 @@ 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_exec_date",comment = "周期合同执行日")//给表加注释 @jakarta.persistence.Table(name = "contract_exec_date")//数据库创建的表明 public class ContractExecDate extends BaseModel<ContractExecDate> { @Schema(description = "关联合同ID") @Column(columnDefinition = "bigint not null comment '关联合同ID'") private Long contractId; @Schema(description = "关联标的物ID") @Column(columnDefinition = "bigint not null comment '关联标的物ID'") private Long matterId; @Schema(description = "执行日期") @Column(columnDefinition="date comment '执行日期'") @JsonFormat(pattern = "yyyy-MM-dd") private Date execDate; @Schema(description = "生成标识") @Column(columnDefinition="char comment '生成标识 0/未生 1/已生'") private String genFlag; } platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractSubjectMatter.java
@@ -14,6 +14,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.util.Date; /** * 合同标的物明细实体类 @@ -156,4 +157,20 @@ @Schema(description = "最近一次交付数量") @Column(columnDefinition = "decimal(10,2) comment '最近一次交付数量'") private BigDecimal lastDeliveredQuantity; @Schema(description = "抄表编号") @Column(columnDefinition="VARCHAR(64) comment '抄表表号'") private String meterReadCode; @Schema(description = "抄表数字") @Column(columnDefinition="decimal(10,0) comment '抄表数字'") private BigDecimal meterReadNum; @Schema(description = "抄表单据名称") @Column(columnDefinition="text comment '单据名称'") private String meterReadAttNames; @Schema(description = "抄表单据路径") @Column(columnDefinition="text comment '单据路径'") private String meterReadAttPaths; } platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/MeterReadRecord.java
New file @@ -0,0 +1,64 @@ 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 java.math.BigDecimal; import java.util.Date; /** * 2026年5月27日 10:40:16 * syt */ @Data @Entity//加了才能自动生成表 @org.hibernate.annotations.Table(appliesTo="meter_read_record",comment = "水电抄表记录")//给表加注释 @jakarta.persistence.Table(name = "meter_read_record")//数据库创建的表明 public class MeterReadRecord extends BaseModel<MeterReadRecord>{ @Schema(description = "关联合同ID") @Column(columnDefinition = "bigint not null comment '关联合同ID'") private Long contractId; @Schema(description = "关联标的物ID") @Column(columnDefinition = "bigint not null comment '关联标的物ID'") private Long matterId; @Schema(description = "合同名称") @Column(columnDefinition = "VARCHAR(64) comment '合同名称'") private String contractName; @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="VARCHAR(64) comment '抄表数字'") private String meterReadCode; @Schema(description = "抄表数字") @Column(columnDefinition="decimal(10,0) comment '抄表数字'") private BigDecimal meterReadNum; @Schema(description = "抄表时间") @Column(columnDefinition="datetime comment '出库时间'") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date meterReadTime; @Schema(description = "抄表单据名称") @Column(columnDefinition="text comment '单据名称'") private String meterReadAttNames; @Schema(description = "抄表单据路径") @Column(columnDefinition="text comment '单据路径'") private String meterReadAttPaths; } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractController.java
@@ -143,7 +143,7 @@ /** * 定时生成应收款账目 * 定时生成应收逾期 * @return R */ @GetMapping("/genCurrentOverdue" ) @@ -153,6 +153,16 @@ } /** * 定时生成周期性应收 * @return R */ @GetMapping("/genCycleReceiced" ) @Inner(value = false) public R genCycleReceiced() { return contractService.genCycleReceiced(); } /** * 生成新合同 * @param id id * @return R platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/MeterReadRecordController.java
New file @@ -0,0 +1,124 @@ 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.business.dto.MeterReadRecordUpdateDTO; import com.by4cloud.platformx.common.core.util.R; import com.by4cloud.platformx.common.log.annotation.SysLog; import com.by4cloud.platformx.business.entity.MeterReadRecord; import com.by4cloud.platformx.business.service.MeterReadRecordService; 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-27 13:58:57 */ @RestController @RequiredArgsConstructor @RequestMapping("/meterReadRecord" ) @Tag(description = "meterReadRecord" , name = "水电抄表管理" ) @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) public class MeterReadRecordController { private final MeterReadRecordService meterReadRecordService; /** * 分页查询 * @param page 分页对象 * @param meterReadRecord 水电抄表 * @return */ @Operation(summary = "分页查询" , description = "分页查询" ) @GetMapping("/page" ) @PreAuthorize("@pms.hasPermission('business_meterReadRecord_view')" ) public R getMeterReadRecordPage(@ParameterObject Page page, @ParameterObject MeterReadRecord meterReadRecord) { LambdaQueryWrapper<MeterReadRecord> wrapper = Wrappers.lambdaQuery(); wrapper.like(StrUtil.isNotBlank(meterReadRecord.getBusGuestName()),MeterReadRecord::getBusGuestName,meterReadRecord.getBusGuestName()); wrapper.like(StrUtil.isNotBlank(meterReadRecord.getContractName()),MeterReadRecord::getContractName,meterReadRecord.getContractName()); wrapper.orderByDesc(MeterReadRecord::getCreateTime); return R.ok(meterReadRecordService.page(page, wrapper)); } /** * 通过id查询水电抄表 * @param id id * @return R */ @Operation(summary = "通过id查询" , description = "通过id查询" ) @GetMapping("/{id}" ) @PreAuthorize("@pms.hasPermission('business_meterReadRecord_view')" ) public R getById(@PathVariable("id" ) Long id) { return R.ok(meterReadRecordService.getById(id)); } /** * 新增水电抄表 * @param meterReadRecord 水电抄表 * @return R */ @Operation(summary = "新增水电抄表" , description = "新增水电抄表" ) @SysLog("新增水电抄表" ) @PostMapping @PreAuthorize("@pms.hasPermission('business_meterReadRecord_add')" ) public R save(@RequestBody MeterReadRecord meterReadRecord) { return R.ok(meterReadRecordService.save(meterReadRecord)); } /** * 修改水电抄表 * @param updateDTO 水电抄表 * @return R */ @Operation(summary = "修改水电抄表" , description = "修改水电抄表" ) @SysLog("修改水电抄表" ) @PutMapping @PreAuthorize("@pms.hasPermission('business_meterReadRecord_edit')" ) public R updateById(@RequestBody MeterReadRecordUpdateDTO updateDTO) { return meterReadRecordService.edit(updateDTO); } /** * 通过id删除水电抄表 * @param ids id列表 * @return R */ @Operation(summary = "通过id删除水电抄表" , description = "通过id删除水电抄表" ) @SysLog("通过id删除水电抄表" ) @DeleteMapping @PreAuthorize("@pms.hasPermission('business_meterReadRecord_del')" ) public R removeById(@RequestBody Long[] ids) { return R.ok(meterReadRecordService.removeBatchByIds(CollUtil.toList(ids))); } /** * 导出excel 表格 * @param meterReadRecord 查询条件 * @param ids 导出指定ID * @return excel 文件流 */ @ResponseExcel @GetMapping("/export") @PreAuthorize("@pms.hasPermission('business_meterReadRecord_export')" ) public List<MeterReadRecord> export(MeterReadRecord meterReadRecord,Long[] ids) { return meterReadRecordService.list(Wrappers.lambdaQuery(meterReadRecord).in(ArrayUtil.isNotEmpty(ids), MeterReadRecord::getId, ids)); } } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/ContractExecDateMapper.java
New file @@ -0,0 +1,11 @@ package com.by4cloud.platformx.business.mapper; import com.by4cloud.platformx.business.entity.ContractExecDate; import com.by4cloud.platformx.common.data.datascope.PlatformxBaseMapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface ContractExecDateMapper extends PlatformxBaseMapper<ContractExecDate> { } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/mapper/MeterReadRecordMapper.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.MeterReadRecord; import org.apache.ibatis.annotations.Mapper; @Mapper public interface MeterReadRecordMapper extends PlatformxBaseMapper<MeterReadRecord> { } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractService.java
@@ -36,4 +36,6 @@ * @param response */ void exportContractYMJJGCLWord(Long id,HttpServletResponse response); R genCycleReceiced(); } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/MeterReadRecordService.java
New file @@ -0,0 +1,11 @@ package com.by4cloud.platformx.business.service; import com.by4cloud.platformx.business.dto.MeterReadRecordUpdateDTO; import com.by4cloud.platformx.business.entity.MeterReadRecord; import com.by4cloud.platformx.common.core.util.R; import com.by4cloud.platformx.common.data.mybatis.IIService; public interface MeterReadRecordService extends IIService<MeterReadRecord> { R edit(MeterReadRecordUpdateDTO updateDTO); } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java
@@ -55,6 +55,8 @@ private final PaymentConfirmMapper paymentConfirmMapper; private final CurrentOverdueMapper currentOverdueMapper; private final BusinessCustomerMapper businessCustomerMapper; private final MeterReadRecordMapper meterReadRecordMapper; private final ContractExecDateMapper contractExecDateMapper; private final RemoteFlowProcessService remoteFlowProcessService; private final ContractTemplateMapper contractTemplateMapper; private final RemoteDeptService remoteDeptService; @@ -88,7 +90,20 @@ subjectMatter.setDeliveryStatus(0); subjectMatter.setTotalAmount(contractSubjectMatterAddDTO.getQuantity().multiply(contractSubjectMatterAddDTO.getUnitPrice())); contractSubjectMatterMapper.insert(subjectMatter); //水电类必须有初次表号 if (StrUtil.isNotEmpty(contractSubjectMatterAddDTO.getMeterReadCode()) && ObjUtil.isNotNull(contractSubjectMatterAddDTO.getMeterReadNum())) { MeterReadRecord record = BeanUtil.copyProperties(contractSubjectMatterAddDTO, MeterReadRecord.class,"id"); record.setContractId(contract.getId()); record.setMatterId(subjectMatter.getId()); record.setContractName(contract.getContractName()); record.setBusGuestId(contract.getPartyAId()); record.setBusGuestName(contract.getPartyA()); record.setMeterReadTime(new Date()); meterReadRecordMapper.insert(record); } }); } if (ArrayUtil.isNotEmpty(addDTO.getContractPaymentSchedule())) { @@ -128,6 +143,9 @@ } if (StrUtil.isNotEmpty(addDTO.getContractCategory()) && StrUtil.equals(addDTO.getContractCategory(), "water_house")) { } return R.ok(); } @@ -228,20 +246,78 @@ Contract contract = baseMapper.selectById(id); contract.setContractStatus(2); baseMapper.updateById(contract); ContractPaymentSchedule fitstSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId()) .orderByAsc(ContractPaymentSchedule::getCreateTime).last("limit 1")); if (fitstSchedule.getStageName().equals("合同签订")) { //新增应收 savePaymentConfirm(contract, fitstSchedule); if (StrUtil.isNotEmpty(contract.getContractCategory()) && StrUtil.equals(contract.getContractCategory(), "water_house")) { List<ContractSubjectMatter> subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery() .eq(ContractSubjectMatter::getContractId,id)); if (ArrayUtil.isNotEmpty(subjectMatterList.toArray())) { subjectMatterList.stream().forEach(contractSubjectMatter -> { //新增合同履约记录 ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess(); process.setContractId(contract.getId()); process.setContractName(contract.getContractName()); process.setScheduleId(fitstSchedule.getId()); process.setScheduleName(fitstSchedule.getStageName()); process.setProcessDate(contract.getSignDate()); contractPaymentScheduleProcessMapper.insert(process); //循环日期 Date execDate0 = DateUtil.offsetDay(contract.getSignDate(), contract.getExecDay()); for (int i = 0; i < contract.getExecTimes(); i++) { if (StrUtil.equals(contract.getExecFrequency(), "1")) { Date execDatei = DateUtil.offsetWeek(execDate0, i); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); contractExecDateMapper.insert(execDate); } if (StrUtil.equals(contract.getExecFrequency(), "2")) { Date execDatei = DateUtil.offsetMonth(execDate0, i ); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); contractExecDateMapper.insert(execDate); } if (StrUtil.equals(contract.getExecFrequency(), "3")) { Date execDatei = DateUtil.offsetMonth(execDate0, i * 3); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); contractExecDateMapper.insert(execDate); } if (StrUtil.equals(contract.getExecFrequency(), "4")) { Date execDatei = DateUtil.offsetMonth(execDate0, i * 6); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); contractExecDateMapper.insert(execDate); } if (StrUtil.equals(contract.getExecFrequency(), "5")) { Date execDatei = DateUtil.offsetYear(execDate0, i); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); contractExecDateMapper.insert(execDate); } } }); } } else { ContractPaymentSchedule fitstSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId()) .orderByAsc(ContractPaymentSchedule::getCreateTime).last("limit 1")); if (fitstSchedule.getStageName().equals("合同签订")) { //新增应收 savePaymentConfirm(contract, fitstSchedule); //新增合同履约记录 ContractPaymentScheduleProcess process = new ContractPaymentScheduleProcess(); process.setContractId(contract.getId()); process.setContractName(contract.getContractName()); process.setScheduleId(fitstSchedule.getId()); process.setScheduleName(fitstSchedule.getStageName()); process.setProcessDate(contract.getSignDate()); contractPaymentScheduleProcessMapper.insert(process); // //当前为合同最后阶段 // PaymentConfirm newConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId()) // .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); @@ -250,74 +326,75 @@ // contract.setContractStatus(3); // baseMapper.updateById(contract); // } } else if (fitstSchedule.getStageName().equals("发货前")) { //更新合同下个阶段 contract.setNextScheduleName("无"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("货到签收")) { //更新合同下个阶段 contract.setNextScheduleName("货到签收"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("调试完成或验收")) { //更新合同下个阶段 contract.setNextScheduleName("调试完成或验收"); baseMapper.updateById(contract); } else { //新增应收 savePaymentConfirm(contract, fitstSchedule); } //查询是否有后续阶段 List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery() .eq(ContractPaymentSchedule::getContractId, fitstSchedule.getContractId()) .gt(ContractPaymentSchedule::getStageOrder, fitstSchedule.getStageOrder()) .orderByAsc(ContractPaymentSchedule::getCreateTime)); if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() == 1) { //最后阶段生效时间 ContractPaymentSchedule endSchedule = afterSchedule.get(0); if (StrUtil.equals(endSchedule.getStageName(), "质保金")) { } else if (fitstSchedule.getStageName().equals("发货前")) { //更新合同下个阶段 contract.setNextScheduleName("无"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("货到签收")) { //更新合同下个阶段 contract.setNextScheduleName("货到签收"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("调试完成或验收")) { //更新合同下个阶段 contract.setNextScheduleName("调试完成或验收"); baseMapper.updateById(contract); } else { //新增应收 savePaymentConfirm(contract, fitstSchedule); } //查询是否有后续阶段 List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery() .eq(ContractPaymentSchedule::getContractId, fitstSchedule.getContractId()) .gt(ContractPaymentSchedule::getStageOrder, fitstSchedule.getStageOrder()) .orderByAsc(ContractPaymentSchedule::getCreateTime)); if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() == 1) { //最后阶段生效时间 ContractPaymentSchedule endSchedule = afterSchedule.get(0); if (StrUtil.equals(endSchedule.getStageName(), "质保金")) { // endSchedule.setEffectiveEndDate(DateUtil.offsetDay(new Date(),endSchedule.getAgreedDays())); // contractPaymentScheduleMapper.updateById(endSchedule); //最后阶段应收 PaymentConfirm newConfim = new PaymentConfirm(); newConfim.setBusinessType(endSchedule.getStageName() + "应收"); newConfim.setBusGuestId(contract.getPartyAId()); newConfim.setBusGuestName(contract.getPartyA()); newConfim.setContractId(contract.getId()); newConfim.setContractName(contract.getContractName()); newConfim.setContractNo(contract.getContractNo()); newConfim.setScheduleId(endSchedule.getId()); newConfim.setScheduleName(endSchedule.getStageName()); newConfim.setConfirmTime(new Date()); newConfim.setTransationAmount(endSchedule.getPlannedAmount()); newConfim.setReceivableAmount(endSchedule.getPlannedAmount()); PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); BigDecimal lastNewTotal = new BigDecimal("0"); if (ObjUtil.isNotNull(lastNewConfirm)) { lastNewTotal = lastNewConfirm.getTotalAmount(); //最后阶段应收 PaymentConfirm newConfim = new PaymentConfirm(); newConfim.setBusinessType(endSchedule.getStageName() + "应收"); newConfim.setBusGuestId(contract.getPartyAId()); newConfim.setBusGuestName(contract.getPartyA()); newConfim.setContractId(contract.getId()); newConfim.setContractName(contract.getContractName()); newConfim.setContractNo(contract.getContractNo()); newConfim.setScheduleId(endSchedule.getId()); newConfim.setScheduleName(endSchedule.getStageName()); newConfim.setConfirmTime(new Date()); newConfim.setTransationAmount(endSchedule.getPlannedAmount()); newConfim.setReceivableAmount(endSchedule.getPlannedAmount()); PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); BigDecimal lastNewTotal = new BigDecimal("0"); if (ObjUtil.isNotNull(lastNewConfirm)) { lastNewTotal = lastNewConfirm.getTotalAmount(); } newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount())); if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { paymentConfirmMapper.insert(newConfim); } } newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount())); if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { paymentConfirmMapper.insert(newConfim); } //更新合同下个阶段 contract.setNextScheduleName(endSchedule.getStageName()); baseMapper.updateById(contract); } //更新合同下个阶段 contract.setNextScheduleName(endSchedule.getStageName()); baseMapper.updateById(contract); } if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() > 1) { //第一阶段生效时间 if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() > 1) { //第一阶段生效时间 // fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays())); // contractPaymentScheduleMapper.updateById(fitstSchedule); //更新合同下个阶段 contract.setNextScheduleName(afterSchedule.get(0).getStageName()); baseMapper.updateById(contract); } //只有当前合同签字阶段 //更新合同下个阶段 contract.setNextScheduleName(afterSchedule.get(0).getStageName()); baseMapper.updateById(contract); } //只有当前合同签字阶段 // if(ArrayUtil.isEmpty(afterSchedule.toArray())){ // fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays())); // contractPaymentScheduleMapper.updateById(fitstSchedule); // } } } private void savePaymentConfirm(Contract contract, ContractPaymentSchedule schedule) { @@ -378,9 +455,9 @@ //更新当前阶段实际收款 和 收款状态 schedule.setActualAmount(inConfirm.getTransationAmount()); schedule.setPaymentStatus(2); if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0){ if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) { inConfirm.setAdvanceAmount(inConfirm.getTotalAmount()); }else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) { } else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) { inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1"))); schedule.setActualAmount(currentInSum); schedule.setPaymentStatus(1); @@ -391,7 +468,7 @@ } }else { } else { paymentConfirmMapper.insert(paymentConfirm); } } @@ -592,4 +669,63 @@ e.printStackTrace(); } } @Override public R genCycleReceiced() { List<ContractExecDate> execDateList = contractExecDateMapper.selectList(Wrappers.<ContractExecDate>lambdaQuery() .le(ContractExecDate::getExecDate, DateUtil.today()).eq(ContractExecDate::getGenFlag,"0")); if (ArrayUtil.isNotEmpty(execDateList.toArray())) { execDateList.stream().forEach(contractExecDate -> { Contract contract = baseMapper.selectById(contractExecDate.getContractId()); ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery() .eq(ContractSubjectMatter::getContractId, contractExecDate.getContractId()) .eq(ContractSubjectMatter::getId, contractExecDate.getMatterId())); //生成抄表单 if (StrUtil.isNotEmpty(subjectMatter.getMeterReadCode()) && ObjUtil.isNotNull(subjectMatter.getMeterReadNum())) { MeterReadRecord record = BeanUtil.copyProperties(subjectMatter, MeterReadRecord.class, "id","meterReadNum"); record.setMatterId(subjectMatter.getId()); record.setBusGuestId(contract.getPartyAId()); record.setBusGuestName(contract.getPartyA()); meterReadRecordMapper.insert(record); }else { //房屋租赁生成应收 PaymentConfirm confirm = new PaymentConfirm(); confirm.setBusinessType("房屋租赁应收"); confirm.setBusGuestId(contract.getPartyAId()); confirm.setBusGuestName(contract.getPartyA()); confirm.setContractId(contract.getId()); confirm.setContractName(contract.getContractName()); confirm.setContractNo(contract.getContractNo()); confirm.setConfirmTime(contractExecDate.getExecDate()); confirm.setTransationAmount(subjectMatter.getUnitPrice().multiply(subjectMatter.getQuantity())); confirm.setTotalAmount(confirm.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)) { BigDecimal total = lastConfirm.getTotalAmount().add(confirm.getTotalAmount()); if (total.compareTo(new BigDecimal("0")) > 0) { confirm.setAdvanceAmount(total); confirm.setTotalAmount(total); } else if (total.compareTo(new BigDecimal("0")) == 0) { confirm.setTotalAmount(total); } else { confirm.setReceivableAmount(total.multiply(new BigDecimal("-1"))); confirm.setTotalAmount(total); } confirm.setCompId(contract.getCompId()); paymentConfirmMapper.insert(confirm); } else { confirm.setReceivableAmount(confirm.getTransationAmount()); confirm.setTotalAmount(confirm.getReceivableAmount().multiply(new BigDecimal("-1"))); confirm.setCompId(contract.getCompId()); paymentConfirmMapper.insert(confirm); } } contractExecDate.setGenFlag("1"); contractExecDateMapper.updateById(contractExecDate); }); } return R.ok(); } } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/MeterReadRecordServiceImpl.java
New file @@ -0,0 +1,92 @@ package com.by4cloud.platformx.business.service.impl; import cn.hutool.core.util.ObjUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.by4cloud.platformx.business.dto.MeterReadRecordUpdateDTO; import com.by4cloud.platformx.business.entity.Contract; import com.by4cloud.platformx.business.entity.ContractSubjectMatter; import com.by4cloud.platformx.business.entity.MeterReadRecord; import com.by4cloud.platformx.business.entity.PaymentConfirm; import com.by4cloud.platformx.business.mapper.ContractMapper; import com.by4cloud.platformx.business.mapper.ContractSubjectMatterMapper; import com.by4cloud.platformx.business.mapper.MeterReadRecordMapper; import com.by4cloud.platformx.business.mapper.PaymentConfirmMapper; import com.by4cloud.platformx.business.service.MeterReadRecordService; import com.by4cloud.platformx.common.core.util.R; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.math.BigDecimal; /** * 水电抄表 * * @author syt * @date 2026-05-27 13:58:57 */ @Service @RequiredArgsConstructor public class MeterReadRecordServiceImpl extends ServiceImpl<MeterReadRecordMapper, MeterReadRecord> implements MeterReadRecordService { private final ContractMapper contractMapper; private final ContractSubjectMatterMapper contractSubjectMatterMapper; private final PaymentConfirmMapper paymentConfirmMapper; @Override public R edit(MeterReadRecordUpdateDTO updateDTO) { MeterReadRecord record = baseMapper.selectById(updateDTO.getId()); MeterReadRecord lastRecord = baseMapper.selectOne(Wrappers.<MeterReadRecord>lambdaQuery().eq(MeterReadRecord::getContractId,updateDTO.getContractId()) .eq(MeterReadRecord::getMeterReadCode,updateDTO.getMeterReadCode()).lt(MeterReadRecord::getCreateTime,record.getCreateTime()) .orderByDesc(MeterReadRecord::getCreateTime).last("limit 1")); if(ObjUtil.isNull(lastRecord)){ return R.failed("无最近抄号记录"); } if (updateDTO.getMeterReadNum().compareTo(lastRecord.getMeterReadNum())<0){ return R.failed("抄号数字不能比上次少"); } record.setMeterReadTime(updateDTO.getMeterReadTime()); record.setMeterReadNum(updateDTO.getMeterReadNum()); record.setMeterReadAttNames(updateDTO.getMeterReadAttNames()); record.setMeterReadAttPaths(updateDTO.getMeterReadAttPaths()); baseMapper.updateById(record); //房屋租赁生成应收 Contract contract = contractMapper.selectById(updateDTO.getContractId()); ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectById(updateDTO.getMatterId()); if(ObjUtil.isNull(lastRecord)){ R.failed("无合同信息,请联系技术人员"); } PaymentConfirm confirm = new PaymentConfirm(); confirm.setBusinessType(subjectMatter.getMaterialInternalName()+"应收"); confirm.setBusGuestId(contract.getPartyAId()); confirm.setBusGuestName(contract.getPartyA()); confirm.setContractId(contract.getId()); confirm.setContractName(contract.getContractName()); confirm.setContractNo(contract.getContractNo()); confirm.setConfirmTime(updateDTO.getMeterReadTime()); confirm.setTransationAmount(subjectMatter.getUnitPrice().multiply(updateDTO.getMeterReadNum().subtract(lastRecord.getMeterReadNum()))); confirm.setTotalAmount(confirm.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)) { BigDecimal total = lastConfirm.getTotalAmount().add(confirm.getTotalAmount()); if (total.compareTo(new BigDecimal("0")) > 0) { confirm.setAdvanceAmount(total); confirm.setTotalAmount(total); } else if (total.compareTo(new BigDecimal("0")) == 0) { confirm.setTotalAmount(total); } else { confirm.setReceivableAmount(total.multiply(new BigDecimal("-1"))); confirm.setTotalAmount(total); } confirm.setCompId(contract.getCompId()); paymentConfirmMapper.insert(confirm); } else { confirm.setReceivableAmount(confirm.getTransationAmount()); confirm.setTotalAmount(confirm.getReceivableAmount().multiply(new BigDecimal("-1"))); confirm.setCompId(contract.getCompId()); paymentConfirmMapper.insert(confirm); } return R.ok(); } } platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -387,13 +387,13 @@ if (contract.getAmount().compareTo(contract.getPaidAmount()) == 0) { contract.setBillingStatus("2"); contract.setContractStatus(3); contractService.updateById(contract); payCompleteContractList.add(contract); } //付款 且 付款未全付 if (contract.getAmount().compareTo(contract.getPaidAmount()) > 0) { payNoCompleteContractList.add(contract); } contractService.updateById(contract); } }); @@ -715,13 +715,13 @@ if (contract.getAmount().compareTo(contract.getPaidAmount()) == 0) { contract.setBillingStatus("2"); contract.setContractStatus(3); contractService.updateById(contract); payCompleteContractList.add(contract); } //付款 且 付款未全付 if (contract.getAmount().compareTo(contract.getPaidAmount()) > 0) { payNoCompleteContractList.add(contract); } contractService.updateById(contract); } }); platformx-business-finance-biz/src/main/resources/mapper/ContractExecDateMapper.xml
New file @@ -0,0 +1,18 @@ <?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.ContractExecDateMapper"> <resultMap id="contractOutBoundMap" type="com.by4cloud.platformx.business.entity.ContractExecDate"> <id property="id" column="id"/> <result property="compId" column="comp_id"/> <result property="contractId" column="contract_id"/> <result property="execDate" column="exec_date"/> <result property="genFlag" column="gen_flag"/> <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/MeterReadRecordMapper.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.MeterReadRecordMapper"> <resultMap id="meterReadRecordMap" type="com.by4cloud.platformx.business.entity.MeterReadRecord"> <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="contractId" column="contract_id"/> <result property="contractName" column="contract_name"/> <result property="meterReadAttNames" column="meter_read_att_names"/> <result property="meterReadAttPaths" column="meter_read_att_paths"/> <result property="meterReadCode" column="meter_read_code"/> <result property="meterReadNum" column="meter_read_num"/> <result property="meterReadTime" column="meter_read_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>