shiyunteng
9 天以前 fb9fca375c78c5b79acf6db990357816f86100fb
platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractServiceImpl.java
@@ -1,10 +1,29 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
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.business.entity.Contract;
import com.by4cloud.platformx.business.mapper.ContractMapper;
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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @author cd
@@ -12,6 +31,280 @@
 * @date 2026/4/29 14:07
 **/
@Service
@RequiredArgsConstructor
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {
   private final ContractSubjectMatterMapper contractSubjectMatterMapper;
   private final ContractPaymentScheduleMapper contractPaymentScheduleMapper;
   private final ContractPaymentScheduleProcessMapper contractPaymentScheduleProcessMapper;
   private final PaymentConfirmMapper paymentConfirmMapper;
   private final CurrentOverdueMapper currentOverdueMapper;
   @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.setBillingStatus("0");
      contract.setErpPushFlag("0");
      List<Contract> contracts;
      contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,contract.getContractNo()));
      while (ArrayUtil.isNotEmpty(contracts.toArray())){
         contract.setContractNo(ContractNumberGenerator.generateContractNumber());
         contracts = baseMapper.selectList(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo,contract.getContractNo()));
      }
      baseMapper.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 (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.setEffectiveDate(DateUtil.offsetDay(contract.getSignDate(),contractPaymentScheduleAddDTO.getAgreedDays()));
            }
            if (ObjUtil.isNotNull(schedule.getEffectiveDate())) {
               if (schedule.getEffectiveDate().before(DateUtil.date())) {
                  schedule.setFulfillmentStatus(1);
               } else {
                  schedule.setFulfillmentStatus(0);
               }
            }
            schedule.setPaymentStatus(0);
            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.setContractNo(ContractNumberGenerator.generateContractNumber());
      baseMapper.updateById(contract);
      if (ArrayUtil.isNotEmpty(updateDTO.getContractSubjectMatter())){
         contractSubjectMatterMapper.delete(Wrappers.<ContractSubjectMatter>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 (ArrayUtil.isNotEmpty(updateDTO.getContractPaymentSchedule())){
         contractPaymentScheduleMapper.delete(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId,contract.getId()));
         AtomicInteger index = new AtomicInteger(1);
         updateDTO.getContractPaymentSchedule().stream().forEach(contractPaymentScheduleAddDTO -> {
            int currentIndex = index.getAndIncrement();
            ContractPaymentSchedule subjectMatter = BeanUtil.copyProperties(contractPaymentScheduleAddDTO, ContractPaymentSchedule.class);
            subjectMatter.setContractId(contract.getId());
            subjectMatter.setContractName(contract.getContractName());
            subjectMatter.setPlannedAmount(contract.getAmount().multiply(subjectMatter.getPaymentRatio().divide(new BigDecimal("100"))));
            subjectMatter.setStageOrder(currentIndex);
            contractPaymentScheduleMapper.insert(subjectMatter);
         });
      }
      return R.ok();
   }
   @Override
   public ContractDetailVo detail(Long id) {
      Contract contract = baseMapper.selectById(id);
      ContractDetailVo detailVo = BeanUtil.copyProperties(contract,ContractDetailVo.class);
      List<ContractSubjectMatter> subjectMatterList = contractSubjectMatterMapper.selectList(Wrappers.<ContractSubjectMatter>lambdaQuery().eq(ContractSubjectMatter::getContractId,id));
      detailVo.setContractSubjectMatter(subjectMatterList);
      List<ContractPaymentSchedule> paymentScheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId,contract.getId()));
      detailVo.setContractPaymentSchedule(paymentScheduleList);
      return detailVo;
   }
   @Override
   public Boolean takeEffect(Long id) {
      Contract contract = baseMapper.selectById(id);
      contract.setContractStatus(1);
      baseMapper.updateById(contract);
      ContractPaymentSchedule fitstSchedule = contractPaymentScheduleMapper.selectOne(Wrappers.<ContractPaymentSchedule>lambdaQuery().eq(ContractPaymentSchedule::getContractId,contract.getId())
            .orderByAsc(ContractPaymentSchedule::getCreateTime).last("limit 1"));
//      PaymentConfirm entity = new PaymentConfirm();
//      entity.setContractId(contract.getId());
//      entity.setContractName(contract.getContractName());
//      entity.setContractNo(contract.getContractNo());
//      entity.setBusGuestId(contract.getPartyAId());
//      entity.setBusGuestName(contract.getPartyA());
//      entity.setBusinessType(fitstSchedule.getStageName()+"应收");
//      entity.setTransationAmount(new BigDecimal(fitstSchedule.getPlannedAmount()));
//      entity.setReceivableAmount(new BigDecimal(fitstSchedule.getPlannedAmount()));
//      entity.setTotalAmount(new BigDecimal("0").subtract(new BigDecimal(fitstSchedule.getPlannedAmount())));
//      entity.setConfirmTime(new Date());
//      paymentConfirmMapper.insert(entity);
      if (fitstSchedule.getStageName().equals("合同签订")){
         //新增应收
         PaymentConfirm paymentConfirm = new PaymentConfirm();
         paymentConfirm.setBusinessType("合同签订应收");
         paymentConfirm.setBusGuestId(contract.getPartyAId());
         paymentConfirm.setBusGuestName(contract.getPartyA());
         paymentConfirm.setContractId(contract.getId());
         paymentConfirm.setContractName(contract.getContractName());
         paymentConfirm.setContractNo(contract.getContractNo());
         paymentConfirm.setScheduleId(fitstSchedule.getId());
         paymentConfirm.setScheduleName(fitstSchedule.getStageName());
         paymentConfirm.setConfirmTime(new Date());
         paymentConfirm.setTransationAmount(fitstSchedule.getPlannedAmount());
         paymentConfirm.setReceivableAmount(fitstSchedule.getPlannedAmount());
         paymentConfirm.setTotalAmount(fitstSchedule.getPlannedAmount().multiply(new BigDecimal("-1")));
         paymentConfirmMapper.insert(paymentConfirm);
         //新增合同履约记录
         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);
      }
      //查询是否有后续阶段
      List<ContractPaymentSchedule> afterSchedule = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
            .eq(ContractPaymentSchedule::getContractId, fitstSchedule.getContractId())
            .gt(ContractPaymentSchedule::getStageOrder, fitstSchedule.getStageOrder()));
      if (ArrayUtil.isNotEmpty(afterSchedule.toArray())&&afterSchedule.size()==1){
         //最后阶段生效时间
         ContractPaymentSchedule endSchedule = afterSchedule.get(0);
         endSchedule.setEffectiveDate(DateUtil.offsetDay(new Date(),endSchedule.getAgreedDays()));
         endSchedule.setEffectiveEndDate(contract.getExpirationDate());
         contractPaymentScheduleMapper.updateById(endSchedule);
         //第一阶段生效时间
         fitstSchedule.setEffectiveDate(DateUtil.offsetDay(new Date(),fitstSchedule.getAgreedDays()));
         fitstSchedule.setEffectiveEndDate(endSchedule.getEffectiveDate());
         contractPaymentScheduleMapper.updateById(fitstSchedule);
         //最后阶段应收
         PaymentConfirm newConfim = new PaymentConfirm();
         newConfim.setBusinessType(endSchedule.getStageName()+"应收");
         newConfim.setBusGuestId(contract.getPartyAId());
         newConfim.setBusGuestName(contract.getPartyA());
         newConfim.setContractId(contract.getId());
         newConfim.setContractName(contract.getContractName());
         newConfim.setContractNo(contract.getContractNo());
         newConfim.setScheduleId(endSchedule.getId());
         newConfim.setScheduleName(endSchedule.getStageName());
         newConfim.setConfirmTime(new Date());
         newConfim.setTransationAmount(endSchedule.getPlannedAmount());
         newConfim.setReceivableAmount(endSchedule.getPlannedAmount());
         PaymentConfirm lastNewConfirm = paymentConfirmMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId,contract.getId())
               .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
         BigDecimal lastNewTotal = new BigDecimal("0");
         if(ObjUtil.isNotNull(lastNewConfirm)){
            lastNewTotal = lastNewConfirm.getTotalAmount();
         }
         newConfim.setTotalAmount(lastNewTotal.subtract(newConfim.getReceivableAmount()));
         paymentConfirmMapper.insert(newConfim);
      }
      if(ArrayUtil.isEmpty(afterSchedule.toArray())){
         fitstSchedule.setEffectiveEndDate(contract.getExpirationDate());
         contractPaymentScheduleMapper.updateById(fitstSchedule);
      }
      return Boolean.TRUE;
   }
   @Override
   public R genCurrentOverdue() {
      List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
            .lt(ContractPaymentSchedule::getEffectiveEndDate, DateUtil.today())
            .ne(ContractPaymentSchedule::getPaymentStatus,"2"));
      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.<PaymentConfirm>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.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getScheduleId, contractPaymentSchedule.getId())
                  .eq(PaymentConfirm::getBusinessType, "应收超期"));
            if (ObjUtil.isNull(oiverdueConfirm)) {
               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.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getContractId,currentOverdue.getContractId())
                  .eq(CurrentOverdue::getScheduleId,currentOverdue.getScheduleId()).last("limit 1"));
            if (ObjUtil.isNull(overdue)){
               currentOverdueMapper.insert(currentOverdue);
            }else {
               overdue.setOverdueDuration(BigDecimal.valueOf(DateUtil.betweenDay(contractPaymentSchedule.getEffectiveEndDate(),new Date(),true)));
               currentOverdueMapper.updateById(overdue);
            }
         });
      }
      return R.ok();
   }
}