liyong
2026-05-25 714ec3cc8e9c0ab12660c1371e832b7dc5532964
feat(approve): 添加销售审批功能并优化相关服务

- 新增销售审批类型(类型9)及其对应的审批流程处理
- 在ApproveProcess实体中添加recordId字段用于存储业务ID
- 实现销售审批成功后自动生成生产数据的功能
- 更新销售台账产品处理逻辑以支持合同号参数传递
- 重构ApproveNodeServiceImpl中的审批流程处理代码结构
- 移除无用的导入包和变量声明,优化代码整洁性
- 调整销售台账服务中的产品处理方法参数列表
- 实现销售审批流程的通知消息处理机制
已修改8个文件
91 ■■■■ 文件已修改
src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
@@ -2,12 +2,10 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.CommonFile;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@@ -47,6 +45,8 @@
     */
    private String approveReason;
    private Long recordId;
    @Excel(name = "开始时间", dateFormat = "yyyy-MM-dd",width = 30)
    @JsonFormat(pattern = "yyyy-MM-dd")
    @ApiModelProperty(value = "开始时间")
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
@@ -78,6 +78,8 @@
    @ApiModelProperty(value = "申请原因")
    @Excel(name = "审批事由")
    private String approveReason;
    //业务id
    private Long recordId;
    /**
     * 当前审批用户ID
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.approve.mapper.ApproveNodeMapper;
@@ -15,7 +14,6 @@
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.device.mapper.DeviceRepairMapper;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.other.service.impl.TempFileServiceImpl;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.project.system.domain.SysUser;
@@ -40,6 +38,7 @@
import com.ruoyi.sales.pojo.SalesQuotation;
import com.ruoyi.sales.pojo.ShippingInfo;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import com.ruoyi.sales.service.impl.SalesLedgerProductServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -72,6 +71,7 @@
    private final QualityTestStandardMapper qualityTestStandardMapper;
    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
    private final QualityInspectParamMapper qualityInspectParamMapper;
    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
    public ApproveProcess getApproveById(String id) {
@@ -230,6 +230,12 @@
            }
        }
        //销售审批成功之后添加生产数据
        if (approveProcess.getApproveType().equals(9)) {
            List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
                    .eq(SalesLedgerProduct::getSalesLedgerId, approveProcess.getRecordId()));
            salesLedgerProducts.forEach(salesLedgerProductServiceImpl::addProductionData);
        }
        // 绑定附件
        if (!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1) {
            tempFileService.migrateTempFilesToFormal(approveNode.getId(), approveNode.getTempFileIds(), FileNameType.ApproveNode.getValue());
@@ -304,6 +310,8 @@
                return "发货审批";
            case 8:
                return "危险作业审批";
            case 9:
                return "销售审批";
        }
        return null;
    }
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -100,6 +100,7 @@
        approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? new Date(): dateFormat.parse(approveProcessVO.getApproveTime()));
        approveProcess.setApproveReason(approveProcessVO.getApproveReason());
        approveProcess.setDeviceRepairId(approveProcessVO.getDeviceRepairId());
        approveProcess.setRecordId(approveProcessVO.getRecordId());
        approveProcess.setMaintenancePrice(approveProcessVO.getMaintenancePrice());
        approveProcess.setPrice(approveProcessVO.getPrice());
        approveProcess.setStartDate(approveProcessVO.getStartDate());
@@ -433,6 +434,8 @@
                return "发货审批";
            case 8:
                return "危险作业审批";
            case 9:
                return "销售审批";
        }
        return null;
    }
src/main/java/com/ruoyi/projectManagement/service/impl/InfoServiceImpl.java
@@ -24,7 +24,6 @@
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -57,7 +56,7 @@
            contractInfoHandleService.save(infoId, saveInfoVo.getContractInfo());
        }
        if(saveInfoVo.getSalesLedgerProductList() != null){
            salesLedgerService.handleSalesLedgerProducts(infoId, saveInfoVo.getSalesLedgerProductList(), SaleEnum.MANAGEMENT);
            salesLedgerService.handleSalesLedgerProducts(infoId, saveInfoVo.getSalesLedgerProductList(), SaleEnum.MANAGEMENT,"");
        }
    }
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
import com.ruoyi.common.enums.SaleEnum;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.dto.LossProductModelDto;
@@ -35,7 +34,7 @@
    List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(@NotNull Long relateId,@NotNull SaleEnum type);
    List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, @NotNull SaleEnum type);
    void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type);
    void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type,String contractNo);
    SalesLedgerDto getSalesLedgerWithProducts(SalesLedgerDto salesLedgerDto);
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -81,7 +81,6 @@
    private ProductionProductInputMapper productionProductInputMapper;
    private QualityInspectMapper qualityInspectMapper;
    private ShippingInfoMapper shippingInfoMapper;
    private ShippingInfoServiceImpl shippingInfoService;
    private StockUtils stockUtils;
@@ -167,7 +166,7 @@
        List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
                .in(ShippingInfo::getSalesLedgerProductId, Arrays.asList(ids)));
        if (!CollectionUtils.isEmpty(shippingInfos)) {
            shippingInfoService.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
            shippingInfoMapper.deleteBatchIds(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
        }
        // 可能属于多个主表
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -9,8 +9,9 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.approve.bean.vo.ApproveProcessVO;
import com.ruoyi.approve.service.IApproveProcessService;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.enums.FileNameType;
@@ -25,7 +26,6 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.service.ProductionProductMainService;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
@@ -33,7 +33,6 @@
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
@@ -43,7 +42,6 @@
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
@@ -94,40 +92,17 @@
    private final CommonFileServiceImpl commonFileService;
    private final ShippingInfoMapper shippingInfoMapper;
    private final InvoiceLedgerMapper invoiceLedgerMapper;
    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    private final ProductProcessRouteMapper productProcessRouteMapper;
    private final ProcessRouteItemMapper processRouteItemMapper;
    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
    private final ProductWorkOrderMapper productWorkOrderMapper;
    private final ProductionProductMainMapper productionProductMainMapper;
    private final ProductionProductOutputMapper productionProductOutputMapper;
    private final ProductionProductInputMapper productionProductInputMapper;
    private final QualityInspectMapper qualityInspectMapper;
    private final RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    private final IApproveProcessService approveProcessService;
    private final SysDeptMapper sysDeptMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Autowired
    private ProductModelMapper productModelMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductStructureMapper productStructureMapper;
    @Autowired
    private ProductionProductMainService productionProductMainService;
    @Autowired
    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
    ;
    @Autowired
    private SysUserMapper sysUserMapper;
    private final ProductModelMapper productModelMapper;
    private final ProductionProductMainService productionProductMainService;
    private final PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
    private final SysUserMapper sysUserMapper;
    @Override
    public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
@@ -615,7 +590,7 @@
            // 4. 处理子表数据
            List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
            if (productList != null && !productList.isEmpty()) {
                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()), salesLedger.getSalesContractNo());
                updateMainContractAmount(
                        salesLedger.getId(),
                        productList,
@@ -713,7 +688,7 @@
    // 文件迁移方法
    @Override
    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type, String contractNo) {
        // 按ID分组,区分新增和更新的记录
        Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
                .peek(p -> p.setSalesLedgerId(salesLedgerId))
@@ -737,8 +712,22 @@
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProductMapper.insert(salesLedgerProduct);
                //添加销售审批  审批成功之后添加生产数据
                ApproveProcessVO approveProcessVO = new ApproveProcessVO();
                approveProcessVO.setApproveType(9);
                approveProcessVO.setApproveDeptId(SecurityUtils.getDeptId()[0]);
                approveProcessVO.setApproveReason(contractNo);
                approveProcessVO.setRecordId(salesLedgerProduct.getId());
                approveProcessVO.setApproveUser(SecurityUtils.getUserId());
                approveProcessVO.setApproveTime(LocalDate.now().toString());
                approveProcessVO.setApproveId(salesLedgerProduct.getId().toString());
                try {
                    approveProcessService.addApprove(approveProcessVO);
                }catch (Exception e) {
                    log.error("添加销售审批异常", e);
                }
                // 添加生产数据
                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
//                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
            }
        }
    }