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 cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.*; 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.ItemGeneratorUtil; import com.by4cloud.platformx.business.vo.ContractDetailVo; import com.by4cloud.platformx.common.core.util.R; import com.by4cloud.platformx.common.data.datascope.DataScope; 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 lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** * @author cd * @description * @date 2026/4/29 14:07 **/ @Slf4j @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 ProductMapper productMapper; private final RemoteDeptService remoteDeptService; private final ContractDelayOutMapper contractDelayOutMapper; private final ErpRequestRecordMapper erpRequestRecordMapper; private final StringRedisTemplate redisTemplate; @Value("${erp.ymj}") private String ymjErp; @Value("${erp.ymjToken}") private String ymjToken; @Value("${erp.smj}") private String smjErp; @Value("${erp.sgb}") private String sgbErp; @Value("${erp.jxc}") private String jxcErp; @Value("${erp.tfgs}") private String tfgsErp; @Value("${dept.smj}") private String smj; @Value("${dept.sgb}") private String sgb; @Value("${dept.jxc}") private String jxc; @Value("${dept.tfgs}") private String tfgs; @Value("${dept.ymj}") private String ymj; @Override public R add(ContractAddDTO addDTO) { Contract contract = BeanUtil.copyProperties(addDTO, Contract.class); contract.setPartyBId(SecurityUtils.getUser().getCompId()); contract.setPartyB(SecurityUtils.getUser().getCompName()); contract.setPaidAmount(new BigDecimal("0")); contract.setBillingStatus("0"); contract.setErpPushFlag("0"); if (ObjUtil.isNotNull(addDTO.getDeliveryCycle())){ contract.setExpirationDate(DateUtil.offsetDay(addDTO.getSignDate(),addDTO.getDeliveryCycle())); } if (!StrUtil.equals(addDTO.getContractCategory(), "water_house")){ // 假设 list 是你的 List Optional maxDateObj = addDTO.getContractSubjectMatter().stream() .filter(item -> item.getPlannedDeliveryDate() != null) // 过滤掉日期为空的项,避免 NullPointerException .max(Comparator.comparing(ContractSubjectMatterAddDTO::getPlannedDeliveryDate)); if (maxDateObj.isPresent()) { contract.setExpirationDate(maxDateObj.get().getPlannedDeliveryDate()); } } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",smj)){ contract.setContractNo(generateSMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",sgb)){ contract.setContractNo(generateGYBContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",ymj)){ contract.setContractNo(generateYMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",tfgs)){ contract.setContractNo(generateTFContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",jxc)){ contract.setContractNo(generateJXCContractNo()); } 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 (StrUtil.isNotEmpty(addDTO.getContractCategory()) && StrUtil.equals(addDTO.getContractCategory(), "ymjcg") &&ObjUtil.isNotNull(subjectMatter.getPlannedDeliveryDate())&&ObjUtil.isNotNull(contract.getExpirationDate()) &&DateUtil.compare(contract.getExpirationDate(),subjectMatter.getPlannedDeliveryDate())>0) { contract.setExpirationDate(subjectMatter.getPlannedDeliveryDate()); baseMapper.updateById(contract); } }); } 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); } }); } 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.setBillingStatus("0"); contract.setErpPushFlag("0"); contract.setPaidAmount(new BigDecimal("0")); if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",smj)){ contract.setContractNo(generateSMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",sgb)){ contract.setContractNo(generateGYBContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",ymj)){ contract.setContractNo(generateYMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",tfgs)){ contract.setContractNo(generateTFContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",jxc)){ contract.setContractNo(generateJXCContractNo()); } if (ObjUtil.isNotNull(updateDTO.getDeliveryCycle())){ contract.setExpirationDate(DateUtil.offsetDay(updateDTO.getSignDate(),updateDTO.getDeliveryCycle())); } if (!StrUtil.equals(updateDTO.getContractCategory(), "water_house")){ // 假设 list 是你的 List Optional maxDateObj = updateDTO.getContractSubjectMatter().stream() .filter(item -> item.getPlannedDeliveryDate() != null) // 过滤掉日期为空的项,避免 NullPointerException .max(Comparator.comparing(ContractSubjectMatterAddDTO::getPlannedDeliveryDate)); if (maxDateObj.isPresent()) { contract.setExpirationDate(maxDateObj.get().getPlannedDeliveryDate()); } } 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); BusinessCustomer a = businessCustomerMapper.selectById(contract.getPartyAId()); if (ObjUtil.isNotNull(a)){ detailVo.setPartyAOrgCode(a.getCreditCode()); } 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); List subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.lambdaQuery() .eq(ContractSubjectMatter::getContractId,id)); if (StrUtil.isNotEmpty(contract.getContractCategory()) && StrUtil.equals(contract.getContractCategory(), "water_house")) { if (ArrayUtil.isNotEmpty(subjectMatterList.toArray())) { for (ContractSubjectMatter contractSubjectMatter: subjectMatterList) { if (StrUtil.equals(contract.getExecFrequency(), "1")) { Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfWeek(contract.getEffectiveDate()), DateUtil.endOfWeek(contract.getExpirationDate()), true)+1; //循环日期 Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfWeek(contract.getEffectiveDate()), contract.getExecDay()); for (int i = 0; i < weeksTrue.intValue(); i++) { Date execDatei = DateUtil.offsetWeek(execDate0, i); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); if (DateUtil.isIn(execDatei,contract.getEffectiveDate(),contract.getExpirationDate())) { contractExecDateMapper.insert(execDate); } } } if (StrUtil.equals(contract.getExecFrequency(), "2")) { Long weeksTrue = DateUtil.betweenMonth(DateUtil.beginOfMonth(contract.getEffectiveDate()), DateUtil.endOfMonth(contract.getExpirationDate()), true)+1; //循环日期 Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfMonth(contract.getEffectiveDate()), contract.getExecDay()); for (int i = 0; i < weeksTrue.intValue(); i++) { Date execDatei = DateUtil.offsetMonth(execDate0, i); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); if (DateUtil.isIn(execDatei,contract.getEffectiveDate(),contract.getExpirationDate())) { contractExecDateMapper.insert(execDate); } } } if (StrUtil.equals(contract.getExecFrequency(), "3")) { Long weeksTrue = (DateUtil.betweenMonth(DateUtil.beginOfQuarter(contract.getEffectiveDate()), DateUtil.endOfQuarter(contract.getExpirationDate()), true)+1)/3; //循环日期 Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfQuarter(contract.getEffectiveDate()), contract.getExecDay()); for (int i = 0; i < weeksTrue.intValue(); i++) { 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"); if (DateUtil.isIn(execDatei,contract.getEffectiveDate(),contract.getExpirationDate())) { contractExecDateMapper.insert(execDate); } } } if (StrUtil.equals(contract.getExecFrequency(), "4")) { Date startDate = contract.getEffectiveDate(); Date endDate = contract.getExpirationDate(); Integer startMonth = DateUtil.month(contract.getEffectiveDate()); Integer endMonth = DateUtil.month(contract.getExpirationDate()); if (1<=startMonth&&startMonth<=6){ startDate = DateUtil.beginOfYear(startDate); } if (7<=startMonth&&startMonth<=12){ startDate = DateUtil.offsetMonth(DateUtil.beginOfYear(startDate),6); } if (1<=endMonth&&endMonth<=6){ endDate = DateUtil.offsetMonth(DateUtil.endOfYear(endDate),-6); } if (7<=endMonth&&endMonth<=12){ endDate = DateUtil.endOfYear(endDate); } Long weeksTrue = (DateUtil.betweenMonth(startDate,endDate, true)+1)/6; //循环日期 Date execDate0 = DateUtil.offsetDay(startDate, contract.getExecDay()); for (int i = 0; i < weeksTrue.intValue(); i++) { 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"); if (DateUtil.isIn(execDatei,contract.getEffectiveDate(),contract.getExpirationDate())) { contractExecDateMapper.insert(execDate); } } } if (StrUtil.equals(contract.getExecFrequency(), "5")) { Long weeksTrue = DateUtil.betweenWeek(DateUtil.beginOfYear(contract.getEffectiveDate()), DateUtil.endOfYear(contract.getExpirationDate()), true)+1; //循环日期 Date execDate0 = DateUtil.offsetDay(DateUtil.beginOfYear(contract.getEffectiveDate()), contract.getExecDay()); for (int i = 0; i < weeksTrue.intValue(); i++) { Date execDatei = DateUtil.offsetWeek(execDate0, i); ContractExecDate execDate = new ContractExecDate(); execDate.setContractId(contract.getId()); execDate.setMatterId(contractSubjectMatter.getId()); execDate.setExecDate(execDatei); execDate.setGenFlag("0"); if (DateUtil.isIn(execDatei,contract.getEffectiveDate(),contract.getExpirationDate())) { 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); // } } //erp推送 JSONObject request = new JSONObject(); BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId()); request.put("contractNo",contract.getContractNo()); request.put("partyA",contract.getPartyA()); request.put("partyACode",customer.getErpCompanyCode()); if (StrUtil.equals(contract.getPartyBId()+"",ymj)&&StrUtil.isNotEmpty(ymjErp)){ request.put("customerCode",customer.getErpCompanyCode()); request.put("currencyId","RMB"); request.put("signDate",DateUtil.format(contract.getSignDate(),DatePattern.NORM_DATETIME_PATTERN)); request.put("dateDeliver",DateUtil.format(contract.getExpirationDate(),DatePattern.NORM_DATETIME_PATTERN)); request.put("moneySum",contract.getAmount()); request.put("signManner","面签"); request.put("salesman",contract.getCreateBy()); if (ArrayUtil.isNotEmpty(subjectMatterList.toArray())){ JSONArray subjectMatter = new JSONArray(); subjectMatterList.stream().forEach(contractSubjectMatter -> { JSONObject subjectMatterItem = new JSONObject(); subjectMatterItem.put("itemNo",ItemGeneratorUtil.nextId()); subjectMatterItem.put("salePrice",contractSubjectMatter.getUnitPrice()); subjectMatterItem.put("qtyRequired",contractSubjectMatter.getQuantity()); subjectMatterItem.put("money",contractSubjectMatter.getQuantity().multiply(contractSubjectMatter.getUnitPrice())); Product product = productMapper.selectOne(Wrappers.lambdaQuery().eq(Product::getCompId,contract.getCompId()) .eq(Product::getErpCode,contractSubjectMatter.getMaterialCode())); if (ObjUtil.isNotNull(product)){ subjectMatterItem.put("taxRate",new BigDecimal(product.getTaxRate()).divide(new BigDecimal("100"))); } subjectMatterItem.put("dateDeliver",ObjUtil.isNotNull(contractSubjectMatter.getPlannedDeliveryDate())? DateUtil.format(contractSubjectMatter.getPlannedDeliveryDate(),DatePattern.NORM_DATETIME_PATTERN): DateUtil.format(contract.getExpirationDate(),DatePattern.NORM_DATETIME_PATTERN)); subjectMatter.add(subjectMatterItem); }); request.put("details",subjectMatter); } log.info("一煤机合同推送erp入参:{}",request.toJSONString()); HttpResponse response = HttpRequest.post(ymjErp) .header("token", ymjToken) // 添加认证头 .header("Content-Type", "application/json") // 设置内容类型 .body(request.toJSONString()) // 设置请求体 .execute(); // 执行请求.post(ymjErp,request.toJSONString()); log.info("一煤机合同推送erp回参:{}",response.body()); //保存请求记录 saveErpRequestRecord("ymj",request.toJSONString(),response.body()); //更新合同erp推送标识 contract.setErpPushFlag("1"); baseMapper.updateById(contract); } if (StrUtil.equals(contract.getPartyBId()+"",smj)&&StrUtil.isNotEmpty(smjErp)){ log.info("石煤机合同推送erp入参:{}",request.toJSONString()); String result = HttpUtil.post(ymjErp,request.toJSONString()); log.info("石煤机合同推送erp回参:{}",result); //保存请求记录 saveErpRequestRecord("smj",request.toJSONString(),result); //更新合同erp推送标识 contract.setErpPushFlag("1"); baseMapper.updateById(contract); } if (StrUtil.equals(contract.getPartyBId()+"",jxc)&&StrUtil.isNotEmpty(jxcErp)){ log.info("机械厂合同推送erp入参:{}",request.toJSONString()); String result = HttpUtil.post(ymjErp,request.toJSONString()); log.info("机械厂合同推送erp回参:{}",result); //保存请求记录 saveErpRequestRecord("jxc",request.toJSONString(),result); //更新合同erp推送标识 contract.setErpPushFlag("1"); baseMapper.updateById(contract); } if (StrUtil.equals(contract.getPartyBId()+"",tfgs)&&StrUtil.isNotEmpty(tfgsErp)){ //通方公司通过系统录入 } if (StrUtil.equals(contract.getPartyBId()+"",sgb)&&StrUtil.isNotEmpty(sgbErp)){ //石工泵主动推送系统 } } private void saveErpRequestRecord(String ymj, String toJSONString, String result) { ErpRequestRecord record = new ErpRequestRecord(); record.setErpName(ymj); record.setRequestParams(toJSONString); record.setResponseParams(result); erpRequestRecordMapper.insert(record); } 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")); if(ObjUtil.isNotNull(newLastConfirm)){ 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.setPaidAmount(new BigDecimal("0")); newContract.setBillingStatus("0"); newContract.setErpPushFlag("0"); newContract.setContractStatus(0); if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",smj)){ newContract.setContractNo(generateSMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",sgb)){ newContract.setContractNo(generateGYBContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",ymj)){ newContract.setContractNo(generateYMJContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",tfgs)){ newContract.setContractNo(generateTFContractNo()); } if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"",jxc)){ newContract.setContractNo(generateJXCContractNo()); } 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.getRegisterName()); 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/ymj/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(); } @Override public void exportContractYMJGYPMMWord(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()); if (no.get().equals(Integer.valueOf(0))){ item.put("deliveryCycle",contract.getDeliveryCycle()); } items.add(item); no.updateAndGet(v -> v + 1); }); map.put("items", items); //定制方 BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId()); map.put("companyName", customer.getRegisterName()); 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("orgName", 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/ymj/ymjgypmmht.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 void exportContractYMJGKCPMMWord(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())); map.put("deliveryCycle",contract.getDeliveryCycle()); //标的物 List> items = 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.getRegisterName()); 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("orgName", 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/ymj/ymjgkcpmmht.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 void exportContractYMJCGWord(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())); map.put("environment",contract.getEnvironment()); map.put("standard",contract.getStandard()); map.put("useMonth",contract.getUseMonth()); map.put("afterShipMonth",contract.getAfterShipMonth()); map.put("shipMethod",contract.getShipMethod()); map.put("shipAddress",contract.getShipAddress()); map.put("packaging",contract.getPackaging()); map.put("repairPeriod",contract.getRepairPeriod()); map.put("repairBreachAmount",contract.getRepairBreachAmount()); map.put("goodsShort",contract.getGoodsShort()); map.put("goodsShortBreachAmount",contract.getGoodsShortBreachAmount()); map.put("overdueBreachAmount",contract.getOverdueBreachAmount()); map.put("terminateContract",contract.getTerminateContract()); map.put("court",contract.getCourt()); map.put("contractAttchment",contract.getContractAttchment()); map.put("invoiceNotice",contract.getInvoiceNotice()); map.put("city",contract.getCity()); map.put("region",contract.getRegion()); //标的物 List> items = new ArrayList<>(); AtomicReference no = new AtomicReference<>(0); subjectMatterList.stream().forEach(contractSubjectMatter -> { Product product = productMapper.selectOne(Wrappers.lambdaQuery().eq(Product::getErpCode,contractSubjectMatter.getMaterialCode()).last("limit 1")); 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("unitPrice", contractSubjectMatter.getUnitPrice()); item.put("priceTax", contractSubjectMatter.getUnitPrice().multiply(contractSubjectMatter.getQuantity()).setScale(2, RoundingMode.HALF_UP)); item.put("priceNoTax", contractSubjectMatter.getUnitPrice().multiply(contractSubjectMatter.getQuantity()) .subtract(contractSubjectMatter.getUnitPrice().multiply(contractSubjectMatter.getQuantity()) .divide(new BigDecimal("100").add(new BigDecimal(product.getTaxRate())),2, RoundingMode.HALF_UP).multiply(new BigDecimal(product.getTaxRate()))) .setScale(2, RoundingMode.HALF_UP)); item.put("deliveryDate", DateUtil.formatDate(contractSubjectMatter.getPlannedDeliveryDate())); item.put("remarks", contractSubjectMatter.getRemarks()); map.put("taxRate",product.getTaxRate()); items.add(item); no.updateAndGet(v -> v + 1); }); //付款 List scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.lambdaQuery() .eq(ContractPaymentSchedule::getContractId, id).orderByAsc(ContractPaymentSchedule::getCreateTime)); scheduleList.stream().forEach(contractPaymentSchedule -> { if (contractPaymentSchedule.getStageName().equals("合同签订")){ map.put("htqdbl",contractPaymentSchedule.getPaymentRatio()); map.put("htqdje",contractPaymentSchedule.getPlannedAmount()); map.put("htqdjr",contractPaymentSchedule.getAgreedDays()); } if (contractPaymentSchedule.getStageName().equals("发货前")){ map.put("fhqbl",contractPaymentSchedule.getPaymentRatio()); map.put("fhqje",contractPaymentSchedule.getPlannedAmount()); } if (contractPaymentSchedule.getStageName().equals("调试完成或验收")){ map.put("ysbl",contractPaymentSchedule.getPaymentRatio()); map.put("ysje",contractPaymentSchedule.getPlannedAmount()); map.put("ysjr",contractPaymentSchedule.getAgreedDays()); } if (contractPaymentSchedule.getStageName().equals("质保金")){ map.put("zbjbl",contractPaymentSchedule.getPaymentRatio()); map.put("zbjje",contractPaymentSchedule.getPlannedAmount()); map.put("zbjjr",contractPaymentSchedule.getAgreedDays()); } }); map.put("items", items); //定制方 BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId()); map.put("companyName", customer.getRegisterName()); 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("orgName", 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/ymj/ymjcght.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 delayOutApproval(DelayOutApprovalDTO dto) { Contract contract = baseMapper.selectById(dto.getContractId()); ContractDelayOut delayOut = BeanUtil.copyProperties(dto,ContractDelayOut.class); delayOut.setApplyTime(new Date()); delayOut.setApplyName(SecurityUtils.getUser().getUsername()); delayOut.setDelayStatus("0"); Map map = new HashMap<>(); map.put("contractId",contract.getId()); map.put("contractName",contract.getContractName()); map.put("partyA",contract.getPartyA()); map.put("partyB",contract.getPartyB()); map.put("delayDay",dto.getDelayDay()); map.put("applyName",SecurityUtils.getUser().getUsername()); map.put("applyTime",DateUtil.format(delayOut.getApplyTime(),DatePattern.NORM_DATETIME_FORMAT)); //启动流程 ProcessInstanceParamDto paramDto = new ProcessInstanceParamDto(); paramDto.setParamMap(map); paramDto.setFlowName(FlowNameEnum.延期出货审批.name()); R r1 = remoteFlowProcessService.startProcessInstance(paramDto); if (r1.getCode() == 1) { return R.failed("流程启动失败"); } contractDelayOutMapper.insert(delayOut); return R.ok(); } @Override public Page pageScope(Page page, ContracQueryDTO queryDTO) { return baseMapper.pageScope(page,queryDTO, DataScope.of("comp_id")); } @Override public void exportContractTFGSGYPMMWord(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("materialName", contractSubjectMatter.getMaterialName()); item.put("guige", contractSubjectMatter.getSpecification()); item.put("unit", contractSubjectMatter.getUnit()); item.put("quantity", contractSubjectMatter.getQuantity()); 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.getRegisterName()); 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("orgName", 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/tfgs/tfgsgypmmht.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 addContractSgb(ContractAddDTO addDTO) { if (ArrayUtil.isEmpty(addDTO.getContractSubjectMatter().toArray())){ return R.failed("请添加标的物"); } if (ArrayUtil.isEmpty(addDTO.getContractPaymentSchedule().toArray())){ return R.failed("请添加付款阶段或付款阶段缺少"); } if (!isValidPaymentStages(addDTO.getContractPaymentSchedule())){ return R.failed("付款阶段信息异常"); } if (addDTO.getContractPaymentSchedule().stream().map(item->item.getPaymentRatio()).reduce(BigDecimal.ZERO,BigDecimal::add) .compareTo(new BigDecimal("100.00"))!=0){ return R.failed("付款阶段比例异常"); } Contract contract = BeanUtil.copyProperties(addDTO, Contract.class); contract.setErpContractNo(contract.getContractNo()); contract.setPartyBId(SecurityUtils.getUser().getCompId()); contract.setPartyB(SecurityUtils.getUser().getCompName()); contract.setContractStatus(2); contract.setPaidAmount(new BigDecimal("0")); contract.setBillingStatus("0"); contract.setErpPushFlag("1"); if (ObjUtil.isNotNull(addDTO.getDeliveryCycle())){ contract.setExpirationDate(DateUtil.offsetDay(addDTO.getSignDate(),addDTO.getDeliveryCycle())); } contract.setContractNo(generateGYBContractNo()); if (!StrUtil.equals(addDTO.getContractCategory(), "water_house")){ // 假设 list 是你的 List Optional maxDateObj = addDTO.getContractSubjectMatter().stream() .filter(item -> item.getPlannedDeliveryDate() != null) // 过滤掉日期为空的项,避免 NullPointerException .max(Comparator.comparing(ContractSubjectMatterAddDTO::getPlannedDeliveryDate)); if (maxDateObj.isPresent()) { contract.setExpirationDate(maxDateObj.get().getPlannedDeliveryDate()); } } 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 (StrUtil.isNotEmpty(addDTO.getContractCategory()) && StrUtil.equals(addDTO.getContractCategory(), "ymjcg") &&ObjUtil.isNotNull(subjectMatter.getPlannedDeliveryDate())&&ObjUtil.isNotNull(contract.getExpirationDate()) &&DateUtil.compare(contract.getExpirationDate(),subjectMatter.getPlannedDeliveryDate())>0) { contract.setExpirationDate(subjectMatter.getPlannedDeliveryDate()); baseMapper.updateById(contract); } }); } 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); } }); } return R.ok(contract.getId()); } @Override public R updateContractSgb(ContractUpdateDTO updateDTO) { if (ArrayUtil.isEmpty(updateDTO.getContractSubjectMatter().toArray())){ return R.failed("请添加标的物"); } if (ArrayUtil.isEmpty(updateDTO.getContractPaymentSchedule().toArray())){ return R.failed("请添加付款阶段或付款阶段缺少"); } if (!isValidPaymentStages(updateDTO.getContractPaymentSchedule())){ return R.failed("付款阶段信息异常"); } if (updateDTO.getContractPaymentSchedule().stream().map(item->item.getPaymentRatio()).reduce(BigDecimal.ZERO,BigDecimal::add) .compareTo(new BigDecimal("100.00"))!=0){ return R.failed("付款阶段比例异常"); } Contract contract = BeanUtil.copyProperties(updateDTO, Contract.class); if (ObjUtil.isNotNull(updateDTO.getDeliveryCycle())){ contract.setExpirationDate(DateUtil.offsetDay(updateDTO.getSignDate(),updateDTO.getDeliveryCycle())); } if (!StrUtil.equals(updateDTO.getContractCategory(), "water_house")){ // 假设 list 是你的 List Optional maxDateObj = updateDTO.getContractSubjectMatter().stream() .filter(item -> item.getPlannedDeliveryDate() != null) // 过滤掉日期为空的项,避免 NullPointerException .max(Comparator.comparing(ContractSubjectMatterAddDTO::getPlannedDeliveryDate)); if (maxDateObj.isPresent()) { contract.setExpirationDate(maxDateObj.get().getPlannedDeliveryDate()); } } 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(); } // 定义标准的五个阶段 private static final Set VALID_STAGES = new HashSet<>(Arrays.asList( "合同签订", "发货前", "货到签收", "调试完成或验收", "质保金" )); /** * 判断付款阶段列表是否符合标准 * @param scheduleList 付款阶段列表 * @return true 如果包含且仅包含标准的五个阶段,false 否则 */ public static boolean isValidPaymentStages(List scheduleList) { if (scheduleList == null || scheduleList.isEmpty()) { return false; } // 1. 提取所有非空的 stageName List actualStages = scheduleList.stream() .map(ContractPaymentScheduleAddDTO::getStageName) .filter(stage -> stage != null && !stage.trim().isEmpty()) .map(String::trim) .collect(Collectors.toList()); // 2. 基本数量检查:必须正好是5个 if (actualStages.size() != VALID_STAGES.size()) { return false; } // 3. 内容检查:所有实际阶段都必须在标准集合中 // 使用 Set 去重后比较,防止列表中有重复阶段但总数凑够5个的情况 Set actualStageSet = new HashSet<>(actualStages); // 检查实际集合大小是否也为5(确保无重复)且包含于标准集合 return VALID_STAGES.equals(actualStageSet); } /** * 生成格式为: yyyyMMdd + 4位序列号 (例如: 20260629000001) */ public String generateSMJContractNo() { // 1. 获取当前日期字符串 String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); // 2. 构建 Redis Key,按天隔离,例如: order:no:20260629 String key = "ZB-SMJ:" + dateStr; // 3. Redis 原子递增,设置过期时间为2天(防止Key堆积,同时覆盖跨天边界情况) Long sequence = redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, 1, java.util.concurrent.TimeUnit.DAYS); // 4. 格式化序列号,不足6位前补0 String seqStr = String.format("%04d", sequence); // 5. 拼接返回 return "ZB-SMJ-"+dateStr + seqStr; } public String generateYMJContractNo() { // 1. 获取当前日期字符串 String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); // 2. 构建 Redis Key,按天隔离,例如: order:no:20260629 String key = "ZB-YMJ:" + dateStr; // 3. Redis 原子递增,设置过期时间为2天(防止Key堆积,同时覆盖跨天边界情况) Long sequence = redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, 1, java.util.concurrent.TimeUnit.DAYS); // 4. 格式化序列号,不足6位前补0 String seqStr = String.format("%04d", sequence); // 5. 拼接返回 return "ZB-YMJ-"+dateStr + seqStr; } public String generateJXCContractNo() { // 1. 获取当前日期字符串 String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); // 2. 构建 Redis Key,按天隔离,例如: order:no:20260629 String key = "ZB-JXC:" + dateStr; // 3. Redis 原子递增,设置过期时间为2天(防止Key堆积,同时覆盖跨天边界情况) Long sequence = redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, 1, java.util.concurrent.TimeUnit.DAYS); // 4. 格式化序列号,不足6位前补0 String seqStr = String.format("%04d", sequence); // 5. 拼接返回 return "ZB-JXC-"+dateStr + seqStr; } public String generateTFContractNo() { // 1. 获取当前日期字符串 String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); // 2. 构建 Redis Key,按天隔离,例如: order:no:20260629 String key = "ZB-TF:" + dateStr; // 3. Redis 原子递增,设置过期时间为2天(防止Key堆积,同时覆盖跨天边界情况) Long sequence = redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, 1, java.util.concurrent.TimeUnit.DAYS); // 4. 格式化序列号,不足6位前补0 String seqStr = String.format("%04d", sequence); // 5. 拼接返回 return "ZB-TF-"+dateStr + seqStr; } public String generateGYBContractNo() { // 1. 获取当前日期字符串 String dateStr = DateUtil.format(new Date(), "yyyyMMdd"); // 2. 构建 Redis Key,按天隔离,例如: order:no:20260629 String key = "ZB-GYB:" + dateStr; // 3. Redis 原子递增,设置过期时间为2天(防止Key堆积,同时覆盖跨天边界情况) Long sequence = redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, 1, java.util.concurrent.TimeUnit.DAYS); // 4. 格式化序列号,不足6位前补0 String seqStr = String.format("%04d", sequence); // 5. 拼接返回 return "ZB-GYB-"+dateStr + seqStr; } }