package com.by4cloud.platformx.business.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.by4cloud.platformx.admin.api.entity.SysDept; import com.by4cloud.platformx.admin.api.feign.RemoteDeptService; import com.by4cloud.platformx.business.api.feign.RemoteFlowProcessService; import com.by4cloud.platformx.business.constant.FlowNameEnum; import com.by4cloud.platformx.business.dto.ContractAddDTO; import com.by4cloud.platformx.business.dto.ContractUpdateDTO; import com.by4cloud.platformx.business.entity.*; import com.by4cloud.platformx.business.mapper.*; import com.by4cloud.platformx.business.service.ContractService; import com.by4cloud.platformx.business.utils.ContractNumberGenerator; 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.dto.ProcessInstanceParamDto; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.deepoove.poi.data.RowRenderData; import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** * @author cd * @description * @date 2026/4/29 14:07 **/ @Service @RequiredArgsConstructor public class ContractServiceImpl extends ServiceImpl implements ContractService { private final ContractSubjectMatterMapper contractSubjectMatterMapper; private final ContractPaymentScheduleMapper contractPaymentScheduleMapper; private final ContractPaymentScheduleProcessMapper contractPaymentScheduleProcessMapper; 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; @Value("${file.local.base-path}") private String basePath; @Override public R add(ContractAddDTO addDTO) { Contract contract = BeanUtil.copyProperties(addDTO, Contract.class); contract.setPartyBId(SecurityUtils.getUser().getCompId()); contract.setPartyB(SecurityUtils.getUser().getCompName()); contract.setContractNo(ContractNumberGenerator.generateContractNumber()); contract.setPaidAmount(new BigDecimal("0")); contract.setBillingStatus("0"); contract.setErpPushFlag("0"); List contracts; contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, contract.getContractNo())); while (ArrayUtil.isNotEmpty(contracts.toArray())) { contract.setContractNo(ContractNumberGenerator.generateContractNumber()); contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, contract.getContractNo())); } baseMapper.insert(contract); if (ArrayUtil.isNotEmpty(addDTO.getContractSubjectMatter())) { addDTO.getContractSubjectMatter().stream().forEach(contractSubjectMatterAddDTO -> { ContractSubjectMatter subjectMatter = BeanUtil.copyProperties(contractSubjectMatterAddDTO, ContractSubjectMatter.class); subjectMatter.setContractId(contract.getId()); subjectMatter.setContractName(contract.getContractName()); subjectMatter.setDeliveredQuantity(new BigDecimal("0")); 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())) { AtomicInteger index = new AtomicInteger(1); addDTO.getContractPaymentSchedule().stream().forEach(contractPaymentScheduleAddDTO -> { int currentIndex = index.getAndIncrement(); ContractPaymentSchedule schedule = BeanUtil.copyProperties(contractPaymentScheduleAddDTO, ContractPaymentSchedule.class); if (contractPaymentScheduleAddDTO.getStageName().equals("合同签订")) { schedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(), contractPaymentScheduleAddDTO.getAgreedDays())); } if (ObjUtil.isNotNull(schedule.getEffectiveDate())) { if (schedule.getEffectiveDate().before(DateUtil.date())) { schedule.setFulfillmentStatus(1); } else { schedule.setFulfillmentStatus(0); } } if (contractPaymentScheduleAddDTO.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { schedule.setPaymentStatus(0); } else { schedule.setPaymentStatus(3); } 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); } }); } if (StrUtil.isNotEmpty(addDTO.getContractCategory()) && StrUtil.equals(addDTO.getContractCategory(), "water_house")) { } return R.ok(); } @Override public R edit(ContractUpdateDTO updateDTO) { Contract entity = baseMapper.selectById(updateDTO.getId()); if (!StrUtil.equals(entity.getContractStatus() + "", "0")) { return R.failed("当前状态无法修改合同"); } Contract contract = BeanUtil.copyProperties(updateDTO, Contract.class); contract.setContractNo(ContractNumberGenerator.generateContractNumber()); contract.setBillingStatus("0"); contract.setErpPushFlag("0"); contract.setPaidAmount(new BigDecimal("0")); List contracts; contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, contract.getContractNo())); while (ArrayUtil.isNotEmpty(contracts.toArray())) { contract.setContractNo(ContractNumberGenerator.generateContractNumber()); contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, contract.getContractNo())); } baseMapper.updateById(contract); if (ArrayUtil.isNotEmpty(updateDTO.getContractSubjectMatter())) { contractSubjectMatterMapper.delete(Wrappers.lambdaQuery().eq(ContractSubjectMatter::getContractId, contract.getId())); updateDTO.getContractSubjectMatter().stream().forEach(contractSubjectMatterAddDTO -> { ContractSubjectMatter subjectMatter = BeanUtil.copyProperties(contractSubjectMatterAddDTO, ContractSubjectMatter.class); subjectMatter.setContractId(contract.getId()); subjectMatter.setContractName(contract.getContractName()); subjectMatter.setDeliveredQuantity(new BigDecimal("0")); subjectMatter.setDeliveryStatus(0); contractSubjectMatterMapper.insert(subjectMatter); //水电类必须有初次表号 if (StrUtil.isNotEmpty(contractSubjectMatterAddDTO.getMeterReadCode()) && ObjUtil.isNotNull(contractSubjectMatterAddDTO.getMeterReadNum())) { meterReadRecordMapper.delete(Wrappers.lambdaQuery().eq(MeterReadRecord::getContractId, contract.getId())); 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(updateDTO.getContractPaymentSchedule())) { contractPaymentScheduleMapper.delete(Wrappers.lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId())); AtomicInteger index = new AtomicInteger(1); updateDTO.getContractPaymentSchedule().stream().forEach(contractPaymentScheduleAddDTO -> { int currentIndex = index.getAndIncrement(); 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); if (contractPaymentScheduleAddDTO.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { schedule.setPaymentStatus(0); } else { schedule.setPaymentStatus(3); } 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); } }); } return R.ok(); } @Override public ContractDetailVo detail(Long id) { Contract contract = baseMapper.selectById(id); ContractDetailVo detailVo = BeanUtil.copyProperties(contract, ContractDetailVo.class); List subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.lambdaQuery().eq(ContractSubjectMatter::getContractId, id)); detailVo.setContractSubjectMatter(subjectMatterList); List paymentScheduleList = contractPaymentScheduleMapper.selectList(Wrappers.lambdaQuery().eq(ContractPaymentSchedule::getContractId, contract.getId())); detailVo.setContractPaymentSchedule(paymentScheduleList); return detailVo; } @Override public R startApproval(Long id) { Contract contract = baseMapper.selectById(id); //启动流程 ProcessInstanceParamDto dto = new ProcessInstanceParamDto(); Map 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(1); baseMapper.updateById(contract); return R.ok(); } public void takeEffect(Long id) { Contract contract = baseMapper.selectById(id); contract.setContractStatus(2); baseMapper.updateById(contract); if (StrUtil.isNotEmpty(contract.getContractCategory()) && StrUtil.equals(contract.getContractCategory(), "water_house")) { List subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.lambdaQuery() .eq(ContractSubjectMatter::getContractId,id)); if (ArrayUtil.isNotEmpty(subjectMatterList.toArray())) { subjectMatterList.stream().forEach(contractSubjectMatter -> { //循环日期 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.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.lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId()) // .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); // if (ObjUtil.isNotNull(newConfirm)&&newConfirm.getTotalAmount().compareTo(new BigDecimal("0"))>=0){ // //有预付且超过应收 关闭合同状态 // contract.setContractStatus(3); // baseMapper.updateById(contract); // } } else if (fitstSchedule.getStageName().equals("发货前")) { //更新合同下个阶段 contract.setNextScheduleName("无"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("货到签收")) { //更新合同下个阶段 contract.setNextScheduleName("货到签收"); baseMapper.updateById(contract); } else if (fitstSchedule.getStageName().equals("调试完成或验收")) { //更新合同下个阶段 contract.setNextScheduleName("调试完成或验收"); baseMapper.updateById(contract); } else { //新增应收 savePaymentConfirm(contract, fitstSchedule); } //查询是否有后续阶段 List afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.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.lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); BigDecimal lastNewTotal = new BigDecimal("0"); if (ObjUtil.isNotNull(lastNewConfirm)) { lastNewTotal = lastNewConfirm.getTotalAmount(); } newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount())); if (endSchedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { paymentConfirmMapper.insert(newConfim); } } //更新合同下个阶段 contract.setNextScheduleName(endSchedule.getStageName()); baseMapper.updateById(contract); } if (ArrayUtil.isNotEmpty(afterSchedule.toArray()) && afterSchedule.size() > 1) { //第一阶段生效时间 // fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays())); // contractPaymentScheduleMapper.updateById(fitstSchedule); //更新合同下个阶段 contract.setNextScheduleName(afterSchedule.get(0).getStageName()); baseMapper.updateById(contract); } //只有当前合同签字阶段 // if(ArrayUtil.isEmpty(afterSchedule.toArray())){ // fitstSchedule.setEffectiveEndDate(DateUtil.offsetDay(contract.getSignDate(),fitstSchedule.getAgreedDays())); // contractPaymentScheduleMapper.updateById(fitstSchedule); // } } } private void savePaymentConfirm(Contract contract, ContractPaymentSchedule schedule) { PaymentConfirm paymentConfirm = new PaymentConfirm(); paymentConfirm.setBusinessType(schedule.getStageName() + "应收"); paymentConfirm.setBusGuestId(contract.getPartyAId()); paymentConfirm.setBusGuestName(contract.getPartyA()); paymentConfirm.setContractId(contract.getId()); paymentConfirm.setContractName(contract.getContractName()); paymentConfirm.setContractNo(contract.getContractNo()); paymentConfirm.setScheduleId(schedule.getId()); paymentConfirm.setScheduleName(schedule.getStageName()); paymentConfirm.setConfirmTime(new Date()); paymentConfirm.setTransationAmount(schedule.getPlannedAmount()); paymentConfirm.setReceivableAmount(schedule.getPlannedAmount()); paymentConfirm.setTotalAmount(schedule.getPlannedAmount().multiply(new BigDecimal("-1"))); PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); BigDecimal lastNewTotal = new BigDecimal("0"); if (ObjUtil.isNotNull(lastNewConfirm)) { lastNewTotal = lastNewConfirm.getTotalAmount(); } paymentConfirm.setTotalAmount(lastNewTotal.subtract(paymentConfirm.getReceivableAmount())); if (schedule.getPaymentRatio().compareTo(new BigDecimal("0")) > 0) { paymentConfirmMapper.insert(paymentConfirm); } //客户付款完成合同 List customerCompleteContractList = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getPartyAId, contract.getPartyAId()) .eq(Contract::getPartyBId, SecurityUtils.getUser().getCompId()).apply(" amount = paid_amount")); if (ArrayUtil.isNotEmpty(customerCompleteContractList)) { List outAmountList = new ArrayList<>(); for (Contract completeContract : customerCompleteContractList ) { PaymentConfirm contractLastConfirm = paymentConfirmMapper.selectOne(Wrappers.lambdaQuery().eq(PaymentConfirm::getContractId, completeContract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); //查询客户付款完成合同中最后明细金额 有预收转入当前合同 if (contractLastConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) { //新增完成付款合同 资金转出 PaymentConfirm outConfirm = BeanUtil.copyProperties(contractLastConfirm, PaymentConfirm.class, "id", "transationAmount", "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount"); outConfirm.setBusinessType("资金转出"); outConfirm.setConfirmTime(new Date()); outConfirm.setTransationAmount(contractLastConfirm.getTotalAmount()); outConfirm.setTotalAmount(new BigDecimal("0")); paymentConfirmMapper.insert(outConfirm); outAmountList.add(outConfirm.getTransationAmount()); } } if (ArrayUtil.isNotEmpty(outAmountList.toArray())) { BigDecimal currentInSum = outAmountList.stream().reduce(BigDecimal.ZERO, BigDecimal::add); //新增当前合同 资金转入 PaymentConfirm inConfirm = BeanUtil.copyProperties(paymentConfirm, PaymentConfirm.class, "id", "transationAmount", "advanceAmount", "receivableAmount", "overdueAmount", "totalAmount"); inConfirm.setBusinessType("资金转入"); inConfirm.setConfirmTime(new Date()); inConfirm.setTransationAmount(currentInSum); inConfirm.setTotalAmount(paymentConfirm.getTotalAmount().add(currentInSum)); //更新当前阶段实际收款 和 收款状态 schedule.setActualAmount(inConfirm.getTransationAmount()); schedule.setPaymentStatus(2); if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) > 0) { inConfirm.setAdvanceAmount(inConfirm.getTotalAmount()); } else if (inConfirm.getTotalAmount().compareTo(new BigDecimal("0")) < 0) { inConfirm.setReceivableAmount(inConfirm.getTotalAmount().multiply(new BigDecimal("-1"))); schedule.setActualAmount(currentInSum); schedule.setPaymentStatus(1); } paymentConfirmMapper.insert(inConfirm); //更新当前阶段实际收款 和 收款状态 contractPaymentScheduleMapper.updateById(schedule); } } else { paymentConfirmMapper.insert(paymentConfirm); } } @Override public R genCurrentOverdue() { List scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.lambdaQuery() .lt(ContractPaymentSchedule::getEffectiveEndDate, DateUtil.today()) .ne(ContractPaymentSchedule::getPaymentStatus, "2") .ne(ContractPaymentSchedule::getPaymentStatus, 3)); if (ArrayUtil.isNotEmpty(scheduleList.toArray())) { scheduleList.stream().forEach(contractPaymentSchedule -> { Contract contract = baseMapper.selectById(contractPaymentSchedule.getContractId()); //应收超期 PaymentConfirm overdueConfirm = new PaymentConfirm(); overdueConfirm.setBusinessType("应收超期"); overdueConfirm.setBusGuestId(contract.getPartyAId()); overdueConfirm.setBusGuestName(contract.getPartyA()); overdueConfirm.setContractId(contract.getId()); overdueConfirm.setContractName(contract.getContractName()); overdueConfirm.setContractNo(contract.getContractNo()); overdueConfirm.setConfirmTime(new Date()); overdueConfirm.setScheduleId(contractPaymentSchedule.getId()); overdueConfirm.setScheduleName(contractPaymentSchedule.getStageName()); PaymentConfirm newLastConfirm = paymentConfirmMapper.selectOne(Wrappers.lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId()) .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1")); overdueConfirm.setTransationAmount(StrUtil.equals(contractPaymentSchedule.getPaymentStatus() + "", "0") ? contractPaymentSchedule.getPlannedAmount() : contractPaymentSchedule.getPlannedAmount().subtract(contractPaymentSchedule.getActualAmount())); overdueConfirm.setReceivableAmount(newLastConfirm.getTotalAmount().multiply(new BigDecimal("-1"))); overdueConfirm.setOverdueAmount(overdueConfirm.getTransationAmount()); overdueConfirm.setTotalAmount(newLastConfirm.getTotalAmount()); overdueConfirm.setCompId(contract.getCompId()); //判断当前阶段是否已生成上阶段应收超期 PaymentConfirm oiverdueConfirm = paymentConfirmMapper.selectOne(Wrappers.lambdaQuery().eq(PaymentConfirm::getScheduleId, contractPaymentSchedule.getId()) .eq(PaymentConfirm::getBusinessType, "应收超期")); if (ObjUtil.isNull(oiverdueConfirm) && overdueConfirm.getTransationAmount().compareTo(new BigDecimal("0")) > 0) { paymentConfirmMapper.insert(overdueConfirm); } //当前逾期 CurrentOverdue currentOverdue = new CurrentOverdue(); currentOverdue.setBusGuestId(contract.getPartyAId()); currentOverdue.setBusGuestName(contract.getPartyA()); currentOverdue.setContractId(contractPaymentSchedule.getContractId()); currentOverdue.setContractName(contractPaymentSchedule.getContractName()); currentOverdue.setScheduleId(contractPaymentSchedule.getId()); currentOverdue.setScheduleName(contractPaymentSchedule.getStageName()); currentOverdue.setCompId(contract.getCompId()); currentOverdue.setContractExpirTime(contractPaymentSchedule.getEffectiveEndDate()); currentOverdue.setReceivableAmount(StrUtil.equals(contractPaymentSchedule.getPaymentStatus() + "", "0") ? contractPaymentSchedule.getPlannedAmount() : contractPaymentSchedule.getPlannedAmount().subtract(contractPaymentSchedule.getActualAmount())); currentOverdue.setOverdueDuration(BigDecimal.valueOf(DateUtil.betweenDay(contractPaymentSchedule.getEffectiveEndDate(), new Date(), true))); CurrentOverdue overdue = currentOverdueMapper.selectOne(Wrappers.lambdaQuery().eq(CurrentOverdue::getContractId, currentOverdue.getContractId()) .eq(CurrentOverdue::getScheduleId, currentOverdue.getScheduleId()).last("limit 1")); if (ObjUtil.isNull(overdue)) { if (currentOverdue.getReceivableAmount().compareTo(new BigDecimal("0")) > 0) { currentOverdueMapper.insert(currentOverdue); } } else { overdue.setOverdueDuration(BigDecimal.valueOf(DateUtil.betweenDay(contractPaymentSchedule.getEffectiveEndDate(), new Date(), true))); currentOverdueMapper.updateById(overdue); } }); } return R.ok(); } @Override public R refuseApproval(Long id) { Contract contract = baseMapper.selectById(id); contract.setContractStatus(0); baseMapper.updateById(contract); return R.ok(); } @Override public R copyNewContract(Long id) { Contract oldContract = baseMapper.selectById(id); Contract newContract = BeanUtil.copyProperties(oldContract, Contract.class, "id", "createTime"); newContract.setContractNo(ContractNumberGenerator.generateContractNumber()); newContract.setPaidAmount(new BigDecimal("0")); newContract.setBillingStatus("0"); newContract.setErpPushFlag("0"); newContract.setContractStatus(0); List contracts; contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, newContract.getContractNo())); while (ArrayUtil.isNotEmpty(contracts.toArray())) { newContract.setContractNo(ContractNumberGenerator.generateContractNumber()); contracts = baseMapper.selectList(Wrappers.lambdaQuery().eq(Contract::getContractNo, newContract.getContractNo())); } baseMapper.insert(newContract); List subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.lambdaQuery().eq(ContractSubjectMatter::getContractId, id)); subjectMatterList.stream().forEach(contractSubjectMatter -> { ContractSubjectMatter subjectMatter = BeanUtil.copyProperties(contractSubjectMatter, ContractSubjectMatter.class, "id", "createTime"); subjectMatter.setContractId(newContract.getId()); subjectMatter.setDeliveryStatus(0); subjectMatter.setDeliveredQuantity(new BigDecimal("0")); subjectMatter.setRemainingQuantity(new BigDecimal("0")); contractSubjectMatterMapper.insert(subjectMatter); }); List scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.lambdaQuery().eq(ContractPaymentSchedule::getContractId, id)); scheduleList.stream().forEach(contractPaymentSchedule -> { ContractPaymentSchedule schedule = BeanUtil.copyProperties(contractPaymentSchedule, ContractPaymentSchedule.class, "id", "createTime"); schedule.setContractId(newContract.getId()); schedule.setPaymentStatus(0); schedule.setActualAmount(new BigDecimal("0")); schedule.setEffectiveDate(null); schedule.setEffectiveEndDate(null); contractPaymentScheduleMapper.insert(schedule); }); return R.ok(); } @Override public void exportContractYMJJGCLWord(Long id, HttpServletResponse response) { Contract contract = baseMapper.selectById(id); List subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.lambdaQuery() .eq(ContractSubjectMatter::getContractId, id).orderByAsc(ContractSubjectMatter::getCreateTime)); Map map = new HashMap<>(); //合同基本信息 map.put("partyA", contract.getPartyA()); map.put("partyB", contract.getPartyB()); map.put("contractNo", contract.getContractNo()); map.put("signPlace", contract.getSignPlace()); map.put("signDate", DateUtil.formatDate(contract.getSignDate())); map.put("signDateYMD", DateUtil.format(contract.getSignDate(), DatePattern.CHINESE_DATE_PATTERN)); map.put("total", contract.getAmount()); map.put("amountWords", Convert.digitToChinese(contract.getAmount())); //标的物 List> items = new ArrayList<>(); List dataList = new ArrayList<>(); AtomicReference no = new AtomicReference<>(0); subjectMatterList.stream().forEach(contractSubjectMatter -> { Map item = new HashMap<>(); item.put("no", no); item.put("materialName", contractSubjectMatter.getMaterialName()); item.put("guige", contractSubjectMatter.getSpecification()); item.put("unit", contractSubjectMatter.getUnit()); item.put("quantity", contractSubjectMatter.getQuantity()); item.put("danzhong", contractSubjectMatter.getSingleWight()); item.put("zongzhong", contractSubjectMatter.getTotalWight()); item.put("unitPrice", contractSubjectMatter.getUnitPrice()); item.put("price", contractSubjectMatter.getTotalAmount()); items.add(item); no.updateAndGet(v -> v + 1); }); map.put("items", items); //定制方 BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId()); map.put("companyName", customer.getCompanyName()); map.put("legalPerson", customer.getLegalPerson()); map.put("contactPhone", customer.getContactPhone()); map.put("bankName", customer.getBankName()); map.put("bankAccount", customer.getBankAccount()); //承揽方 R r = remoteDeptService.getById(contract.getPartyBId()); SysDept dept = r.getData(); map.put("companyName", dept.getOrgName()); map.put("legalPerson1", StrUtil.isNotEmpty(dept.getLegalPerson()) ? dept.getLegalPerson() : ""); map.put("entrustedAgent", StrUtil.isNotEmpty(dept.getLegalPerson()) ? "" : dept.getEntrustedAgent()); map.put("orgContact", dept.getOrgContact()); map.put("orgBank", dept.getOrgBank()); map.put("orgBankAccount", dept.getOrgBankAccount()); //生成文件名 Long time = new Date().getTime(); // 生成的word格式 String formatSuffix = ".docx"; // 拼接后的文件名 String fileName = time + formatSuffix;//文件名 带后缀 //导出word try { // 1. 加载模版 // 假设模版在 resources/templates/template.docx ClassPathResource resource = new ClassPathResource("template/ymjjgclht.docx"); // 配置列表策略 Configure config = Configure.builder() .bind("items", new LoopRowTableRenderPolicy()) // 将 items 绑定到行循环策略 .build(); // 2. 编译并渲染数据 XWPFTemplate xwpfTemplate = XWPFTemplate.compile(resource.getInputStream(), config).render(map); // 3. 设置响应头 response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".docx"); // 4. 写入输出流 OutputStream out = response.getOutputStream(); xwpfTemplate.write(out); out.flush(); out.close(); xwpfTemplate.close(); // 重要:关闭模版释放资源 } catch (IOException e) { e.printStackTrace(); } } @Override public R genCycleReceiced() { List execDateList = contractExecDateMapper.selectList(Wrappers.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.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 { //创建收款节点 //查询上次收款节点 ContractPaymentSchedule lastSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.lambdaQuery() .eq(ContractPaymentSchedule::getContractId,contract.getId()) .orderByDesc(ContractPaymentSchedule::getCreateTime).last("limit 1")); ContractPaymentSchedule schedule = new ContractPaymentSchedule(); schedule.setStageName("房租租赁缴费"); schedule.setContractId(contract.getId()); schedule.setContractName(contract.getContractName()); schedule.setPlannedAmount(subjectMatter.getUnitPrice().multiply(subjectMatter.getQuantity())); schedule.setEffectiveEndDate(contractExecDate.getExecDate()); schedule.setStageOrder(1); if (ObjUtil.isNotNull(lastSchedule)){ schedule.setStageOrder(lastSchedule.getStageOrder()+1); } schedule.setPaymentStatus(0); schedule.setActualAmount(new BigDecimal("0")); schedule.setCompId(contract.getCompId()); contractPaymentScheduleMapper.insert(schedule); //房屋租赁生成应收 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.setScheduleId(schedule.getId()); confirm.setScheduleName(schedule.getStageName()); confirm.setConfirmTime(contractExecDate.getExecDate()); confirm.setTransationAmount(subjectMatter.getUnitPrice().multiply(subjectMatter.getQuantity())); confirm.setTotalAmount(confirm.getTransationAmount().multiply(new BigDecimal("-1"))); PaymentConfirm lastConfirm = paymentConfirmMapper.selectOne(Wrappers.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(); } }