| | |
| | | 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 |
| | |
| | | * @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(); |
| | | } |
| | | } |