package com.ruoyi.sales.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo; import com.ruoyi.approve.mapper.ApprovalTemplateMapper; import com.ruoyi.approve.pojo.ApprovalInstance; import com.ruoyi.approve.pojo.ApprovalTemplate; import com.ruoyi.approve.pojo.ApproveProcess; import com.ruoyi.approve.service.ApprovalInstanceService; import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.basic.pojo.Customer; import com.ruoyi.common.enums.IsDeleteEnum; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.framework.security.LoginUser; import com.ruoyi.sales.dto.SalesQuotationDto; import com.ruoyi.sales.mapper.SalesQuotationMapper; import com.ruoyi.sales.mapper.SalesQuotationProductMapper; import com.ruoyi.sales.pojo.SalesQuotation; import com.ruoyi.sales.pojo.SalesQuotationProduct; import com.ruoyi.sales.service.SalesQuotationProductService; import com.ruoyi.sales.service.SalesQuotationService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) @RequiredArgsConstructor public class SalesQuotationServiceImpl extends ServiceImpl implements SalesQuotationService { private final SalesQuotationProductMapper salesQuotationProductMapper; private final SalesQuotationMapper salesQuotationMapper; private final SalesQuotationProductService salesQuotationProductService; private final ApproveProcessServiceImpl approveProcessService; private final CustomerMapper customerMapper; private final ApprovalTemplateMapper approvalTemplateMapper; private final ApprovalInstanceService approvalInstanceService; @Override public IPage listPage(Page page, SalesQuotationDto salesQuotationDto) { IPage salesQuotationDtoIPage = salesQuotationMapper.listPage(page, salesQuotationDto); if(CollectionUtils.isEmpty(salesQuotationDtoIPage.getRecords())){ return salesQuotationDtoIPage; } // 批量查询产品,避免 N+1 问题 List quotationIds = salesQuotationDtoIPage.getRecords().stream() .map(SalesQuotationDto::getId) .filter(Objects::nonNull) .collect(Collectors.toList()); if (!quotationIds.isEmpty()) { List allProducts = salesQuotationProductMapper.selectList( new LambdaQueryWrapper() .in(SalesQuotationProduct::getSalesQuotationId, quotationIds) ); Map> productMap = allProducts.stream() .collect(Collectors.groupingBy(SalesQuotationProduct::getSalesQuotationId)); salesQuotationDtoIPage.getRecords().forEach(record -> record.setProducts(productMap.getOrDefault(record.getId(), new ArrayList<>())) ); } return salesQuotationDtoIPage; } @Override public boolean add(SalesQuotationDto salesQuotationDto) { LoginUser loginUser = SecurityUtils.getLoginUser(); SalesQuotation salesQuotation = new SalesQuotation(); BeanUtils.copyProperties(salesQuotationDto, salesQuotation); salesQuotation.setId(null); Customer customer = customerMapper.selectById(Long.valueOf(salesQuotationDto.getCustomerId())); if (ObjectUtils.isNotEmpty(customer)) { salesQuotation.setCustomer(customer.getCustomerName()); } String quotationNo = OrderUtils.countTodayByCreateTime(salesQuotationMapper, "QT","quotation_no", salesQuotationDto.getCreateTime() != null ? salesQuotationDto.getCreateTime() : LocalDateTime.now()); salesQuotation.setQuotationNo(quotationNo); salesQuotation.setStatus("待审批"); salesQuotationMapper.insert(salesQuotation); if(CollectionUtils.isEmpty(salesQuotationDto.getProducts())){ return true; } List products = salesQuotationDto.getProducts().stream().map(product -> { SalesQuotationProduct salesQuotationProduct = new SalesQuotationProduct(); BeanUtils.copyProperties(product, salesQuotationProduct); salesQuotationProduct.setSalesQuotationId(salesQuotation.getId()); return salesQuotationProduct; }).collect(Collectors.toList()); salesQuotationProductService.saveBatch(products); // 报价审批 ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto(); approvalInstance.setTemplateId(approvalTemplateMapper.selectOne(new LambdaQueryWrapper().eq(ApprovalTemplate::getBusinessType,6L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getId()); approvalInstance.setTemplateName(approvalTemplateMapper.selectOne(new LambdaQueryWrapper().eq(ApprovalTemplate::getBusinessType,6L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getTemplateName()); approvalInstance.setBusinessId(salesQuotation.getId()); approvalInstance.setBusinessType(6L); approvalInstance.setCurrentLevel(1); approvalInstance.setTitle(quotationNo+"审批"); approvalInstance.setApplicantId(loginUser.getUserId()); approvalInstance.setApplicantName(loginUser.getNickName()); approvalInstance.setApplyTime(LocalDateTime.now()); try { approvalInstanceService.add(approvalInstance); } catch (Exception e) { log.error("SalesQuotationServiceImpl approve error for quotationNo: {}", e); throw new RuntimeException("审批失败: " + e.getMessage(), e); } return true; } @Override public boolean edit(SalesQuotationDto salesQuotationDto) { SalesQuotation salesQuotation = new SalesQuotation(); BeanUtils.copyProperties(salesQuotationDto, salesQuotation); ApproveGetAndUpdateVo vo = new ApproveGetAndUpdateVo(); if("拒绝".equals(salesQuotationDto.getStatus())){ vo.setApproveStatus(0); salesQuotation.setStatus("待审批"); } if(salesQuotationMapper.updateById(salesQuotation)!=1){ return false; } salesQuotationProductMapper.delete(new LambdaQueryWrapper().eq(SalesQuotationProduct::getSalesQuotationId, salesQuotationDto.getId())); if(CollectionUtils.isEmpty(salesQuotationDto.getProducts())){ return true; } List products = salesQuotationDto.getProducts().stream().map(product -> { SalesQuotationProduct salesQuotationProduct = new SalesQuotationProduct(); BeanUtils.copyProperties(product, salesQuotationProduct); salesQuotationProduct.setSalesQuotationId(salesQuotation.getId()); return salesQuotationProduct; }).collect(Collectors.toList()); salesQuotationProductService.saveBatch(products); // 修改报价审批 // 先结束之前未结束的报价审批 approvalInstanceService.lambdaUpdate().set(ApprovalInstance::getStatus,"REJECTED").eq(ApprovalInstance::getBusinessId,salesQuotation.getId()).eq(ApprovalInstance::getBusinessType,6L).update(); ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto(); approvalInstance.setTemplateId(approvalTemplateMapper.selectOne(new LambdaQueryWrapper().eq(ApprovalTemplate::getBusinessType,6L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getId()); approvalInstance.setTemplateName(approvalTemplateMapper.selectOne(new LambdaQueryWrapper().eq(ApprovalTemplate::getBusinessType,6L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getTemplateName()); approvalInstance.setBusinessId(salesQuotation.getId()); approvalInstance.setBusinessType(6L); approvalInstance.setCurrentLevel(1); approvalInstance.setTitle(salesQuotation.getQuotationNo()+"审批"); approvalInstance.setApplicantId(SecurityUtils.getUserId()); approvalInstance.setApplicantName(SecurityUtils.getLoginUser().getNickName()); approvalInstance.setApplyTime(LocalDateTime.now()); try { approvalInstanceService.add(approvalInstance); } catch (Exception e) { log.error("SalesQuotationServiceImpl approve error for quotationNo: {}", e); throw new RuntimeException("审批失败: " + e.getMessage(), e); } return true; } @Override public boolean delete(Long id) { SalesQuotation salesQuotation = salesQuotationMapper.selectById(id); if(salesQuotation==null) return false; salesQuotationMapper.deleteById(id); salesQuotationProductMapper.delete(new LambdaQueryWrapper().eq(SalesQuotationProduct::getSalesQuotationId, id)); // 删除报价审批 ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper() .eq(ApproveProcess::getApproveType, 6) .eq(ApproveProcess::getApproveDelete, IsDeleteEnum.NOT_DELETED) .eq(ApproveProcess::getApproveReason, salesQuotation.getQuotationNo())); if(one != null){ approveProcessService.delByIds(Collections.singletonList(one.getId())); } return true; } }