liding
2026-04-07 ca1c7d27e81d590f5e48b4102d18898b85d5d2fa
feat:采购/库存入库添加批号
已修改12个文件
152 ■■■■ 文件已修改
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrder.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -126,12 +126,15 @@
     * @param recordType
     * @param recordId
     */
    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId,String batchNo) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        if (batchNo !=null && !batchNo.isEmpty()) {
            stockInventoryDto.setBatchNo(batchNo);
        }
        stockInventoryService.subtractStockInventory(stockInventoryDto);
    }
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -1,13 +1,11 @@
package com.ruoyi.production.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.service.ProductOrderService;
import io.swagger.annotations.Api;
@@ -16,7 +14,6 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
@RequestMapping("productOrder")
@@ -65,9 +62,9 @@
    @ApiOperation("新增生产订单")
    @PostMapping("addProductOrder")
    public R addProductOrder(@RequestBody ProductOrder productOrder) {
        return R.ok(productOrderService.addProductOrder(productOrder));
    @PostMapping("/addProductOrder")
    public R addProductOrder(@RequestBody ProductOrderDto productOrderDto) {
        return R.ok(productOrderService.addProductOrder(productOrderDto));
    }
    @ApiOperation("删除生产订单")
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -62,4 +62,7 @@
    //是否发货(台账页面颜色控制)
    private Boolean isFh;
    @ApiModelProperty(value = "型号")
    private String productModelName;
}
src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -83,4 +83,7 @@
    // 不合格处理结果
    @ApiModelProperty(value = "不合格处理结果")
    private String dealResult;
    @ApiModelProperty(value = "生产批号")
    private String batchNo;
}
src/main/java/com/ruoyi/production/pojo/ProductOrder.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@@ -52,7 +51,7 @@
    private String priority;
    /**
     * 优先级
     * 生产批号
     */
    @ApiModelProperty(value = "生产批号")
    private String batchNo;
src/main/java/com/ruoyi/production/service/ProductOrderService.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.production.dto.ProductBomDto;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.pojo.ProcessRoute;
@@ -22,7 +21,7 @@
    List<ProductStructureDto> listProcessBom(Long orderId);
    Boolean addProductOrder(ProductOrder productOrder);
    Boolean addProductOrder(ProductOrderDto productOrderDto);
    Boolean delete(Long[] id);
}
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -7,8 +7,7 @@
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.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductStructureDto;
@@ -16,7 +15,8 @@
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductOrderService;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.stock.mapper.StockInventoryMapper;
import com.ruoyi.stock.pojo.StockInventory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -24,6 +24,8 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Service
@@ -64,6 +66,9 @@
    @Autowired
    private StockUtils stockUtils;
    @Autowired
    private StockInventoryMapper stockInventoryMapper;
    @Override
    public IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder) {
@@ -135,10 +140,33 @@
    }
    @Override
    public Boolean addProductOrder(ProductOrder productOrder) {
    public Boolean addProductOrder(ProductOrderDto productOrderDto) {
        String string = generateNextOrderNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        ProductOrder productOrder = new ProductOrder();
        BeanUtils.copyProperties(productOrderDto, productOrder);
        productOrder.setNpsNo(string);
        productOrder.setCompleteQuantity(BigDecimal.ZERO);
        List<StockInventory> stockInventoryList = stockInventoryMapper.selectList(null);
        if (productOrder.getBatchNo() == null || productOrder.getBatchNo().isEmpty()) {
            String batchNo;
            // 获取当前月份(两位)
            LocalDate now = LocalDate.now();
            String monthFlag = now.format(DateTimeFormatter.ofPattern("MM"));
            // 获取当前月份的最大流水号
            int maxSeq = getCurrentMonthMaxSeq(productOrderDto.getMaterialCode(),
                    productOrderDto.getProductModelName(), monthFlag, stockInventoryList);
            // 新流水号 = 最大流水号 + 1
            int newSeq = maxSeq + 1;
            String seqStr = String.format("%03d", newSeq);
            // 组装batchNo
            batchNo = productOrderDto.getMaterialCode() + productOrderDto.getProductModelName() + "P" + monthFlag + seqStr;
            productOrder.setBatchNo(batchNo);
        } else {
            productOrder.setBatchNo(productOrder.getBatchNo());
        }
        this.save(productOrder);
        if (ObjectUtils.isNotEmpty(productOrder.getRouteId())) {
            this.bindingRoute(productOrder);
@@ -146,16 +174,38 @@
        return true;
    }
    /**
     * 查询当前月份已存在的最大流水号
     */
    private static int getCurrentMonthMaxSeq(String materialCode, String model, String monthFlag, List<StockInventory> existingList) {
        int maxSeq = 0;
        String prefix = materialCode + model + "P" + monthFlag;
        // 正则匹配:前缀 + 3位数字
        Pattern pattern = Pattern.compile(Pattern.quote(prefix) + "(\\d{3})");
        for (StockInventory item : existingList) {
            String batchNo = item.getBatchNo();
            if (batchNo == null) continue;
            Matcher matcher = pattern.matcher(batchNo);
            if (matcher.find()) {
                int seq = Integer.parseInt(matcher.group(1));
                if (seq > maxSeq) {
                    maxSeq = seq;
                }
            }
        }
        return maxSeq;
    }
    @Override
    public Boolean delete(Long[] ids) {
        //如果已经开始生产,不能删除
        //查询生产订单下的工单
        List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids));
        if (productWorkOrders.size()>0){
        if (productWorkOrders.size() > 0) {
            //判断是否有报工数据
            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery()
                    .in(ProductionProductMain::getWorkOrderId, productWorkOrders.stream().map(ProductWorkOrder::getId).collect(Collectors.toList())));
            if (productionProductMains.size()>0){
            if (productionProductMains.size() > 0) {
                throw new RuntimeException("生产订单已经开始生产,不能删除");
            }
            //删除工单
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -13,8 +13,8 @@
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -32,14 +32,14 @@
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.production.mapper.ProductionProductMainMapper;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@@ -177,7 +177,7 @@
        productionProductMainMapper.insert(productionProductMain);
        /*新增报工投入表*/
        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
        if (productStructureDtos.size() == 0) {
        if (productStructureDtos.isEmpty()) {
            //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个
            ProductStructureDto productStructureDto = new ProductStructureDto();
            productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
@@ -191,8 +191,7 @@
            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
            productionProductInput.setProductMainId(productionProductMain.getId());
            productionProductInputMapper.insert(productionProductInput);
            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(),dto.getBatchNo());
        }
        /*新增报工产出表*/
        ProductionProductOutput productionProductOutput = new ProductionProductOutput();
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -66,7 +66,7 @@
        //扣减库存
        if(!"已发货".equals(byId.getStatus())){
            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(),null);
        }
        byId.setExpressNumber(req.getExpressNumber());
        byId.setExpressCompany(req.getExpressCompany());
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -250,7 +250,8 @@
        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockOutRecordDto.setType("0");
        stockOutRecordService.add(stockOutRecordDto);
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
                .eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            throw new RuntimeException("产品库存不存在");
        }
src/main/resources/application-dev.yml
@@ -28,7 +28,7 @@
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 7003
  port: 8888
  servlet:
    # 应用的访问路径
    context-path: /
@@ -42,13 +42,6 @@
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# 日志配置
logging:
  level:
    org.quartz: DEBUG
    com.ruoyi: warn
    org.springframework: warn
minio:
  endpoint: http://114.132.189.42/
@@ -74,8 +67,10 @@
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/product-inventory-management-new?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#        url: jdbc:mysql://1.15.17.182:9999/product-inventory-management-new?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        url: jdbc:mysql://localhost:3307/product-inventory-management-pcdz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
#        password: xd@123456..
        password: 123456
      # 从库数据源
      slave:
@@ -154,7 +149,7 @@
    database: 0
    # 密码
    #    password: root2022!
    password:
    password: 123456
    # 连接超时时间
    timeout: 10s
@@ -205,16 +200,30 @@
# MyBatis Plus配置
mybatis-plus:
  # 搜索指定包别名   根据自己的项目来
  typeAliasesPackage: com.ruoyi.**.pojo
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 加载全局的配置文件
  configLocation: classpath:mybatis/mybatis-config.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
  type-aliases-package: com.ruoyi.**.pojo
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  global-config:
    enable-sql-runner: true
    banner: false
    db-config:
      id-type: auto
# 日志配置
logging:
  level:
    root: INFO
    com.ruoyi.production.mapper: DEBUG
    org.apache.ibatis: DEBUG
    org.mybatis: DEBUG
    java.sql: DEBUG
    java.sql.Connection: DEBUG
    java.sql.Statement: DEBUG
    java.sql.PreparedStatement: DEBUG
    java.sql.ResultSet: DEBUG
    com.baomidou.mybatisplus: DEBUG
    com.baomidou.mybatisplus.core: DEBUG
# PageHelper分页插件
pagehelper:
@@ -253,4 +262,4 @@
file:
  temp-dir: D:/ruoyi/temp/uploads   # 临时目录
  upload-dir: D:/ruoyi/prod/uploads # 正式目录
  upload-dir: D:/ruoyi/prod/uploads # 正式目录
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -21,6 +21,7 @@
    <select id="pageProductWorkOrder" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
        SELECT
        pwo.*,
        po.batch_no as batchNo,
        pp.id as processId,
        pp.NAME as processName,
        pp.qualified_rate as processQualifiedRate,