5 天以前 92d8d06d8ae38c407715a5e9389691b446413e0a
yys
1.生产逻辑修改
已添加8个文件
已修改51个文件
937 ■■■■ 文件已修改
src/main/java/com/ruoyi/CodeGenerator.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/ProductController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductAndModelDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductModelDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IProductModelService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/FileNameType.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/dto/FileDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProcessRouteController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductProcessController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductStructureController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductStructureRecordController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SysDeptAndUserDto.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductStructureRecordMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrder.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcess.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductStructureRecord.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProcessRouteService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderService.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductStructureRecordService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductStructureService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java 126 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductProcessServiceImpl.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductStructureRecordServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/ProductModelMapper.xml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProcessRouteItemMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProcessRouteMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductBomMapper.xml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMapper.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteMapper.xml 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductStructureMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductStructureRecordMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysDeptMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserDeptMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/CodeGenerator.java
@@ -23,7 +23,7 @@
    public static String database_username = "root";
    public static String database_password= "123456";
    public static String author = "芯导软件(江苏)有限公司";
    public static String model = "sales"; // æ¨¡å—
    public static String model = "production"; // æ¨¡å—
    public static String setParent = "com.ruoyi."+ model; // åŒ…路径
    public static String tablePrefix = ""; // è®¾ç½®è¿‡æ»¤è¡¨å‰ç¼€
    public static void main(String[] args) {
src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -26,6 +26,7 @@
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@RestController
@@ -76,7 +77,7 @@
     */
    @Log(title = "产品规格型号", businessType = BusinessType.INSERT)
    @PostMapping("/addOrEditProductModel")
    public AjaxResult addOrEditProductModel(@RequestBody ProductModelDto productModelDto) {
    public AjaxResult addOrEditProductModel(@RequestBody ProductModelDto productModelDto) throws IOException {
        return toAjax(productModelService.addOrEditProductModel(productModelDto));
    }
src/main/java/com/ruoyi/basic/dto/ProductAndModelDto.java
@@ -2,8 +2,11 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.CommonFile;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author :yys
@@ -12,6 +15,12 @@
@Data
public class ProductAndModelDto {
    private List<CommonFile> SalesLedgerFiles;
    private Long routeId;
    private String routeName;
    /**
     * è§„æ ¼id
     */
src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
@@ -2,6 +2,7 @@
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.sales.pojo.CommonFile;
import lombok.Data;
import java.util.List;
@@ -11,4 +12,7 @@
    private List<ProductStructureDto> productStructureList;
    private String productName;
    private List<String> tempFileIds;
    private List<CommonFile> SalesLedgerFiles;
}
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -20,6 +20,9 @@
    @TableId(type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "工艺路线id")
    private Long routeId;
    /**
     * å…³è”产品id
     */
src/main/java/com/ruoyi/basic/service/IProductModelService.java
@@ -8,6 +8,7 @@
import com.ruoyi.basic.pojo.ProductModel;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@@ -19,7 +20,7 @@
 */
public interface IProductModelService extends IService<ProductModel> {
    int addOrEditProductModel(ProductModelDto productModelDto);
    int addOrEditProductModel(ProductModelDto productModelDto) throws IOException;
    int delProductModel(Long[] ids);
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -16,14 +16,19 @@
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.service.impl.TempFileServiceImpl;
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.AbstractMap;
@@ -45,9 +50,12 @@
    private final ProductMapper productMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
    private ProductModelMapper productModelMapper;
    private final CommonFileServiceImpl commonFileService;
    private final TempFileServiceImpl tempFileService;
    @Override
    public int addOrEditProductModel(ProductModelDto productModelDto) {
    public int addOrEditProductModel(ProductModelDto productModelDto) throws IOException {
        if(StringUtils.isEmpty(productModelDto.getProductName())){
            throw new RuntimeException("产品名称不能为空");
        }
@@ -63,16 +71,23 @@
            ProductModel productModel = new ProductModel();
            BeanUtils.copyProperties(productModelDto,productModel);
            productModel.setProductId(product.getId());
            return productModelMapper.insert(productModel);
            productModelMapper.insert(productModel);
            if(CollectionUtils.isNotEmpty(productModelDto.getTempFileIds())){
                commonFileService.migrateTempFilesToFormal(productModel.getId(), productModelDto.getTempFileIds());
            }
            return 1;
        } else {
            Product product1 = productMapper.selectById(productModelDto.getProductId());
            if(product1 != null){
                product1.setProductName(productModelDto.getProductName());
                productMapper.updateById(product1);
            }
            if(CollectionUtils.isNotEmpty(productModelDto.getTempFileIds())){
                commonFileService.migrateTempFilesToFormal(productModelDto.getId(), productModelDto.getTempFileIds());
            }
            return productModelMapper.updateById(productModelDto);
        }
    }
@@ -116,11 +131,6 @@
        try {
            ExcelUtil<ProductModelExcelCopyDto> productModelExcelUtil = new ExcelUtil<>(ProductModelExcelCopyDto.class);
            List<ProductModelExcelCopyDto> productModelList = productModelExcelUtil.importExcel(file.getInputStream());
//            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>()
//                    .isNull(Product::getParentId));
//            if(CollectionUtils.isEmpty(productList)) {
//                throw new RuntimeException("请先添加父级产品");
//            }
            if(CollectionUtils.isNotEmpty(productModelList)){
                // 2. æŒ‰äº§å“åç§°,图纸编号分组
                Map<Map.Entry<String, String>, List<ProductModelExcelCopyDto>> groupedByProductNameAndDrawingNumber =
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -12,14 +12,17 @@
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.service.IProductService;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -32,6 +35,8 @@
    private ProductMapper productMapper;
    private ProductModelMapper productModelMapper;
    private final CommonFileServiceImpl commonFileService;
    @Override
    public List<ProductTreeDto> selectProductList(ProductDto productDto) {
@@ -64,7 +69,11 @@
    @Override
    public AjaxResult listPage(Page page, ProductAndModelDto productDto) {
        return AjaxResult.success(productModelMapper.listPage(page, productDto));
        IPage<ProductAndModelDto> productAndModelDtoIPage = productModelMapper.listPage(page, productDto);
        productAndModelDtoIPage.getRecords().forEach(item -> {
            item.setSalesLedgerFiles(commonFileService.getFileListByBusinessId(item.getId(), FileNameType.PRODUCT_MODEL.getValue()));
        });
        return AjaxResult.success(productAndModelDtoIPage);
    }
src/main/java/com/ruoyi/common/enums/FileNameType.java
@@ -14,7 +14,9 @@
    SHIP(9),//发货台账
    INSPECTION_PRODUCTION_BEFORE(10),
    INSPECTION_PRODUCTION_AFTER(11),
    INSPECTION(12);//巡检 ç”Ÿäº§å‰
    INSPECTION(12),//巡检 ç”Ÿäº§å‰
    PRODUCT_MODEL(13),// äº§å“åž‹å·å›¾çº¸
    PRODUCT_ORDER(14); //生产订单
    private final int value;
src/main/java/com/ruoyi/dto/FileDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.ruoyi.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.sales.pojo.CommonFile;
import lombok.Data;
import java.util.List;
@Data
public class FileDto {
    @TableField(exist = false)
    private List<String> tempFileIds;
    @TableField(exist = false)
    private List<CommonFile> SalesLedgerFiles;
}
src/main/java/com/ruoyi/production/controller/ProcessRouteController.java
@@ -37,7 +37,7 @@
    @ApiOperation("修改工艺路线")
    @PutMapping ()
    public R update(@RequestBody  ProcessRoute processRoute) {
        return R.ok(processRouteService.updateById(processRoute));
        return R.ok(processRouteService.updateProcessRoute(processRoute));
    }
    @ApiOperation("删除工艺路线")
    @DeleteMapping("/{ids}")
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -16,6 +16,7 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
@@ -32,6 +33,12 @@
    @GetMapping("page")
    public R page(ProductOrderDto productOrder, Page page) {
        return R.ok(productOrderService.pageProductOrder(page, productOrder));
    }
    @ApiOperation("工单开始和暂停")
    @PostMapping("/startOrPause")
    public R startOrPause(@RequestBody ProductOrderDto productOrder) {
        return R.ok(productOrderService.startOrPause(productOrder));
    }
    @ApiOperation("绑定工艺路线")
@@ -89,7 +96,7 @@
    @ApiOperation("新增生产订单")
    @PostMapping("/addProductOrder")
    public R addProductOrder(@RequestBody ProductOrder productOrder) {
    public R addProductOrder(@RequestBody ProductOrder productOrder) throws IOException {
        return R.ok(productOrderService.addProductOrder(productOrder));
    }
src/main/java/com/ruoyi/production/controller/ProductProcessController.java
@@ -11,6 +11,7 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.oA.pojo.OaProject;
import com.ruoyi.production.dto.ProductProcessDto;
import com.ruoyi.production.dto.SysDeptAndUserDto;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.service.impl.ProductProcessServiceImpl;
import io.swagger.annotations.Api;
@@ -33,6 +34,26 @@
    @Autowired
    private ProductProcessServiceImpl productProcessService;
    /**
     * èŽ·å–éƒ¨é—¨ç”¨æˆ·æ ‘
     */
    @GetMapping("/listDeptUserTree")
    @ApiOperation("获取部门用户树")
    public AjaxResult listDeptUserTree() {
        List<SysDeptAndUserDto> list = productProcessService.listDeptUserTree();
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.warn("暂无数据");
        }
        return AjaxResult.success(list);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢å·¥åº
     * @param page
     * @param productProcessDto
     * @return
     */
    @GetMapping("/listPage")
    @Log(title = "工序-分页查询", businessType = BusinessType.OTHER)
    @ApiOperation("工序-分页查询")
src/main/java/com/ruoyi/production/controller/ProductStructureController.java
@@ -26,6 +26,12 @@
    private ProductStructureService productStructureService;
    @ApiOperation("BOM子集列表(无父级)")
    @GetMapping("/listBybomIdIsParent/{bomId}")
    public R listBybomIdIsParent(@PathVariable("bomId") Integer bomId){
        return R.ok(productStructureService.listBybomIdIsParent(bomId));
    }
    @ApiOperation("新增BOM子集")
    @PostMapping()
    public R addOrUpdate(@RequestBody ProductStructureDto productStructureDto){
src/main/java/com/ruoyi/production/controller/ProductStructureRecordController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.production.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * ç”Ÿäº§è®¢å•-物料清单表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-26 10:34:23
 */
@RestController
@RequestMapping("/productStructureRecord")
public class ProductStructureRecordController {
}
src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java
@@ -17,4 +17,7 @@
    private String drawingNumber;
    private String bomNo;
    @ApiModelProperty("工序名称")
    private String processName;
}
src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java
@@ -28,6 +28,8 @@
    private Long productId;
    private String userPower;
    private String model;
}
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -1,6 +1,7 @@
package com.ruoyi.production.dto;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.production.pojo.ProductOrder;
@@ -64,4 +65,7 @@
    @ApiModelProperty(value = "库存数量")
    @Excel(name = "库存数量")
    private BigDecimal inventoryQuantity;
    @ApiModelProperty(value = "操作 1-开始 2-暂停")
    private Integer operation;
}
src/main/java/com/ruoyi/production/dto/SysDeptAndUserDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.ruoyi.production.dto;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import lombok.Data;
import java.util.List;
@Data
public class SysDeptAndUserDto{
    /** éƒ¨é—¨ID */
    private Long deptId;
    /** çˆ¶éƒ¨é—¨ID */
    private Long parentId;
    /** ç¥–级列表 */
    private String ancestors;
    /** éƒ¨é—¨åç§° */
    private String deptName;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** è´Ÿè´£äºº */
    private String leader;
    /** è”系电话 */
    private String phone;
    /** é‚®ç®± */
    private String email;
    /** éƒ¨é—¨çŠ¶æ€:0正常,1停用 */
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** çˆ¶éƒ¨é—¨åç§° */
    private String parentName;
    /** éƒ¨é—¨ç¼–号 */
    private String deptNick;
    /** å‘˜å·¥æ•°é‡ */
    private Integer staffCount;
    /** éƒ¨é—¨ä¸‹çš„用户列表 */
    private List<SysUser> userList;
    /** å­éƒ¨é—¨åˆ—表 */
    private List<SysDeptAndUserDto> childrenList;
}
src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java
@@ -6,6 +6,8 @@
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
 *  Mapper æŽ¥å£
@@ -17,5 +19,5 @@
@Mapper
public interface ProductProcessRouteMapper extends BaseMapper<ProductProcessRoute> {
    ProcessRouteDto listMain(@Param("orderId") Long orderId);
    List<ProcessRouteDto> listMain(@Param("orderId") Long orderId);
}
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java
@@ -13,7 +13,13 @@
@Mapper
public interface ProductStructureMapper  extends BaseMapper<ProductStructure> {
    List<ProductStructureDto> listBybomId(@Param("bomId") Integer bomId);
    /**
     * æŸ¥è¯¢BOM子集
     * @param bomId
     * @param isParent æ˜¯å¦éœ€è¦çˆ¶çº§ true è¿”回子级 false è¿”回子父级
     * @return
     */
    List<ProductStructureDto> listBybomId(@Param("bomId") Integer bomId,@Param("isParent") boolean isParent);
    List<ProductStructureDto> listBybomAndProcess(@Param("bomId") Integer bomId, @Param("processId") Long processId);
}
src/main/java/com/ruoyi/production/mapper/ProductStructureRecordMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.production.mapper;
import com.ruoyi.production.pojo.ProductStructureRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * ç”Ÿäº§è®¢å•-物料清单表 Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-26 10:34:23
 */
@Mapper
public interface ProductStructureRecordMapper extends BaseMapper<ProductStructureRecord> {
}
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
@@ -8,11 +8,16 @@
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@TableName("process_route")
@Data
@ApiModel(value = "processRoute", description = "工艺路线主表")
public class ProcessRoute {
    @TableField(exist = false)
    @ApiModelProperty(value = "工艺路线明细")
    private List<ProcessRouteItem> processRouteItems;
    @ApiModelProperty(value = "序号")
    private Long id;
@@ -23,6 +28,9 @@
    @ApiModelProperty(value = "描述")
    private String description;
    @ApiModelProperty(value = "创建人")
    private String createBy;
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
@@ -39,6 +47,9 @@
    @ApiModelProperty(value = "工艺路线编码")
    private String processRouteCode;
    @ApiModelProperty(value = "工艺路线名称")
    private String processRouteName;
    @ApiModelProperty(value = "BOM的ID")
    private Integer bomId;
}
src/main/java/com/ruoyi/production/pojo/ProductOrder.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.dto.FileDto;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
@@ -10,11 +11,21 @@
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@TableName("product_order")
public class ProductOrder  implements Serializable {
public class ProductOrder extends FileDto implements Serializable {
    @TableField(exist = false)
    @ApiModelProperty(value = "生产任务")
    private List<ProductProcessRouteItem> processRouteItems;
    @TableField(exist = false)
    @ApiModelProperty(value = "物料清单")
    private List<ProductStructureRecord> productStructureRecords;
    private static final long serialVersionUID = 1L;
@@ -101,6 +112,14 @@
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime endTime;
    @ApiModelProperty("交付日期")
    @JsonFormat(pattern = "yyyy-MM-dd",shape = JsonFormat.Shape.STRING,timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "交付日期")
    private LocalDate deliveryDate;
    @ApiModelProperty("状态 å¾…生产 ç”Ÿäº§ä¸­ å·²å®Œæˆ")
    @Excel(name = "状态")
    private String status;
}
src/main/java/com/ruoyi/production/pojo/ProductProcess.java
@@ -42,6 +42,8 @@
    @Excel(name = "备注")
    private String remark;
    @Excel(name = "用户权限(,隔开)")
    private String userPower;
    /**
     * å·¥èµ„定额
src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java
@@ -7,12 +7,15 @@
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
/**
 * <p>
src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
@@ -1,9 +1,12 @@
package com.ruoyi.production.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@@ -12,6 +15,22 @@
    @TableId(type = IdType.AUTO)
    private Long id;
    /**
     * è®¡åˆ’开始时间
     */
    @ApiModelProperty(value = "计划开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate planStartTime;
    /**
     * è®¡åˆ’结束时间
     */
    @ApiModelProperty(value = "计划结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate planEndTime;
    @ApiModelProperty(value = "生产订单id(product_order_id)")
    private Long productOrderId;
@@ -39,6 +58,16 @@
    private Integer dragSort;
    @ApiModelProperty(value ="是否质检")
    private Boolean isQuality;
    private Boolean isQuality = false;
    /**
     * ç”¨æˆ·æƒé™
     */
    @ApiModelProperty(value = "用户报工权限")
    private String userPower;
    @ApiModelProperty(value = "计划数")
    private Integer planNum;
}
src/main/java/com/ruoyi/production/pojo/ProductStructureRecord.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.ruoyi.production.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 * ç”Ÿäº§è®¢å•-物料清单表
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-26 10:34:23
 */
@Getter
@Setter
@TableName("product_structure_record")
@ApiModel(value = "ProductStructureRecord对象", description = "生产订单-物料清单表")
public class ProductStructureRecord implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty("父节点ID")
    private Long parentId;
    @ApiModelProperty("产品id")
    private Long productModelId;
    @ApiModelProperty("生产订单id")
    private Long productOrderId;
    @ApiModelProperty("工序id")
    private Long processId;
    @ApiModelProperty("单位产出需要数量")
    private BigDecimal unitQuantity;
    @ApiModelProperty("需求数量")
    private BigDecimal demandedQuantity;
    @ApiModelProperty("单位")
    private String unit;
    @ApiModelProperty("租户id")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("bom的id")
    private Long bomId;
}
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
@@ -65,9 +65,9 @@
    private String workOrderNo;
    /**
     * çŠ¶æ€  1 å¾…确认  2 å¾…生产 3生产中 4已完成
     * çŠ¶æ€  1 å¾…确认  2 å¾…生产 3生产中
     */
    @ApiModelProperty(value = "状态  1 å¾…确认  2 å¾…生产 3生产中 4已完成")
    @ApiModelProperty(value = "状态  1 å¾…确认  2 å¾…生产 3已完成")
    private Integer status;
    /**
@@ -121,5 +121,14 @@
    @ApiModelProperty(value = "完成数量")
    private BigDecimal completeQuantity;
    /**
     * ç”¨æˆ·æƒé™
     */
    @ApiModelProperty(value = "用户报工权限")
    private String userPower;
    @ApiModelProperty(value = "计划数")
    private Integer planNum;
}
src/main/java/com/ruoyi/production/service/ProcessRouteService.java
@@ -16,4 +16,6 @@
    Integer saveProcessRoute(ProcessRoute processRoute);
    int batchDelete(List<Long> ids);
    int updateProcessRoute(ProcessRoute processRoute);
}
src/main/java/com/ruoyi/production/service/ProductOrderService.java
@@ -9,6 +9,7 @@
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import java.io.IOException;
import java.util.List;
@@ -22,7 +23,9 @@
    List<ProductStructureDto> listProcessBom(Long orderId);
    Boolean addProductOrder(ProductOrder productOrder);
    Boolean addProductOrder(ProductOrder productOrder) throws IOException;
    Boolean delete(Long[] id);
    Object startOrPause(ProductOrderDto productOrder);
}
src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java
@@ -4,6 +4,8 @@
import com.ruoyi.production.pojo.ProductProcessRoute;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
 * <p>
 *  æœåŠ¡ç±»
@@ -14,5 +16,5 @@
 */
public interface ProductProcessRouteService extends IService<ProductProcessRoute> {
    ProcessRouteDto listMain(Long orderId);
    List<ProcessRouteDto> listMain(Long orderId);
}
src/main/java/com/ruoyi/production/service/ProductStructureRecordService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.production.service;
import com.ruoyi.production.pojo.ProductStructureRecord;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * ç”Ÿäº§è®¢å•-物料清单表 æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-26 10:34:23
 */
public interface ProductStructureRecordService extends IService<ProductStructureRecord> {
}
src/main/java/com/ruoyi/production/service/ProductStructureService.java
@@ -14,4 +14,5 @@
    List<ProductStructureDto> listBybomId(Integer bomId);
    List<ProductStructureDto> listBybomIdIsParent(Integer bomId);
}
src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java
@@ -1,9 +1,12 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
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.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.production.dto.ProcessRouteDto;
import com.ruoyi.production.mapper.ProcessRouteItemMapper;
import com.ruoyi.production.mapper.ProcessRouteMapper;
@@ -47,12 +50,23 @@
    @Override
    public Integer saveProcessRoute(ProcessRoute processRoute) {
        String nickName = SecurityUtils.getLoginUser().getNickName();
        processRoute.setCreateBy(nickName);
        this.save(processRoute);
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String idStr = String.format("%06d", processRoute.getId());
        String newProductCode = "GYLX" + dateStr + idStr;
        // æ›´æ–°æ•°æ®åº“中的productCode
        processRoute.setProcessRouteCode(newProductCode);
        // æ–°å¢žå­è¡¨æ•°æ®
        if(CollectionUtils.isNotEmpty(processRoute.getProcessRouteItems())){
            for (ProcessRouteItem processRouteItem : processRoute.getProcessRouteItems()) {
                processRouteItem.setRouteId(processRoute.getId());
                processRouteItemMapper.insert(processRouteItem);
            }
        }
        if(StringUtils.isEmpty(processRoute.getProcessRouteCode())){
            String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String idStr = String.format("%06d", processRoute.getId());
            String newProductCode = "GYLX" + dateStr + idStr;
            // æ›´æ–°æ•°æ®åº“中的productCode
            processRoute.setProcessRouteCode(newProductCode);
        }
        return processRouteMapper.updateById(processRoute);
    }
@@ -60,11 +74,24 @@
    public int batchDelete(List<Long> ids) {
        //先判断是否已经引用了
        List<ProductOrder> productOrders = productOrderMapper.selectList(Wrappers.<ProductOrder>lambdaQuery().in(ProductOrder::getRouteId, ids));
        if (productOrders.size()>0){
        if (CollectionUtils.isNotEmpty(productOrders)){
            throw new RuntimeException("该工艺路线生产已引用,不能删除");
        }
        //删除工艺路线详情
        processRouteItemMapper.delete(Wrappers.<ProcessRouteItem>lambdaQuery().in(ProcessRouteItem::getRouteId, ids));
        return processRouteMapper.deleteBatchIds(ids);
    }
    @Override
    public int updateProcessRoute(ProcessRoute processRoute) {
        this.updateById(processRoute);
        processRouteItemMapper.delete(Wrappers.<ProcessRouteItem>lambdaQuery().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
        if(CollectionUtils.isNotEmpty(processRoute.getProcessRouteItems())){
            for (ProcessRouteItem processRouteItem : processRoute.getProcessRouteItems()) {
                processRouteItem.setRouteId(processRoute.getId());
                processRouteItemMapper.insert(processRouteItem);
            }
        }
        return 1;
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -2,6 +2,7 @@
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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.pojo.Product;
@@ -97,6 +98,53 @@
        return AjaxResult.error();
    }
    /**
     * é€’归保存 BOM:先保存父项 â†’ ä¿å­˜å­é¡¹ â†’ å»ºç«‹å…³ç³» â†’ é€’归子项的子项
     * @param children å½“前父项的子项列表
     * @return ä¿å­˜åŽçš„父项产品ID
     */
    private void saveBomRecursive(List<BomImportDto> children,ProductBom bom,ProductModel rootModel,Map<String, Long> processMap) {
        // 1. èŽ·å–children中子项产品编号为空的数据
        List<BomImportDto> parentChildren = children
                .stream()
                .filter(child -> StringUtils.isEmpty(child.getChildCode()))
                .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(parentChildren)){
            throw new ServiceException("请选择父项产品编号");
        }
        BomImportDto parentId = parentChildren.get(0); // çˆ¶çº§æ•°æ®
        ProductStructure rootNode = new ProductStructure();
        rootNode.setBomId(bom.getId());
        rootNode.setParentId(null); // é¡¶å±‚没有父节点
        rootNode.setProductModelId(rootModel.getId());
        rootNode.setUnitQuantity(BigDecimal.ONE);
        rootNode.setUnit(rootModel.getUnit());
        productStructureService.save(rootNode);
        // 2. éåŽ†å­é¡¹ï¼Œé€ä¸ªå¤„ç†
        for (BomImportDto child : children) {
            //  è·³è¿‡æ²¡æœ‰å­é¡¹çš„父项
            if(StringUtils.isEmpty(child.getChildCode())){
                continue;
            }
            //  èŽ·å–å­é¡¹æ¨¡åž‹ä¿¡æ¯
            ProductModel childModel = findModel(child.getChildName(), child.getChildSpec());
            //  æ’入结构表
            ProductStructure node = new ProductStructure();
            node.setBomId(bom.getId());
            node.setParentId(rootNode.getId()); // çˆ¶èŠ‚ç‚¹ID
            node.setProductModelId(childModel.getId());
            node.setUnitQuantity(child.getUnitQty());
            node.setUnit(childModel.getUnit());
            if (processMap.containsKey(child.getProcess())) {
                node.setProcessId(processMap.get(child.getProcess()));
            }
            productStructureService.save(node);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult uploadBom(MultipartFile file) {
@@ -120,67 +168,25 @@
        handleProcess(list);
        Map<String, Long> processMap = productProcessService.list().stream()
                .collect(Collectors.toMap(ProductProcess::getName, ProductProcess::getId, (k1, k2) -> k1));
        //  åˆ›å»º BOM æ•°æ®
        BomImportDto first = list.get(0);
        ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec());
        ProductBom bom = new ProductBom();
        bom.setProductModelId(rootModel.getId());
        bom.setVersion("1.0");
        productBomMapper.insert(bom);
        bom.setBomNo("BM." + String.format("%05d", bom.getId()));
        productBomMapper.updateById(bom);
        // è®°å½•已经插入结构的节点:Key = "名称+规格", Value = structure_id
        Map<String, Long> treePathMap = new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            BomImportDto dto = list.get(i);
            String parentKey = dto.getParentName() + "|" + dto.getParentSpec();
            String childKey = dto.getChildName() + "|" + dto.getChildSpec();
            //处理根节点,第一行且子项为空
            if (i == 0 && StringUtils.isBlank(dto.getChildName())) {
                ProductStructure rootNode = new ProductStructure();
                rootNode.setBomId(bom.getId());
                rootNode.setParentId(null); // é¡¶å±‚没有父节点
                rootNode.setProductModelId(rootModel.getId());
                rootNode.setUnitQuantity(BigDecimal.ONE);
                rootNode.setUnit(rootModel.getUnit());
                productStructureService.save(rootNode);
                treePathMap.put(parentKey, rootNode.getId());
                continue;
            }
            //  å¤„理子层级节点
            //  æ‰¾åˆ°çˆ¶èŠ‚ç‚¹åœ¨æ•°æ®åº“é‡Œçš„ ID
            Long parentStructureId = treePathMap.get(parentKey);
            if (parentStructureId == null) {
                // å¦‚æžœ Map é‡Œæ‰¾ä¸åˆ°ï¼Œè¯´æ˜Ž Excel é¡ºåºä¹±äº†æˆ–者数据有误
                throw new ServiceException("导入失败: çˆ¶é¡¹[" + dto.getParentName() + "]必须在其子项之前定义");
            }
            //  èŽ·å–å­é¡¹æ¨¡åž‹ä¿¡æ¯
            ProductModel childModel = findModel(dto.getChildName(), dto.getChildSpec());
            //  æ’入结构表
            ProductStructure node = new ProductStructure();
            node.setBomId(bom.getId());
            node.setParentId(parentStructureId); // çˆ¶èŠ‚ç‚¹ID
            node.setProductModelId(childModel.getId());
            node.setUnitQuantity(dto.getUnitQty());
            node.setUnit(childModel.getUnit());
            if (processMap.containsKey(dto.getProcess())) {
                node.setProcessId(processMap.get(dto.getProcess()));
            }
            productStructureService.save(node);
            //  æŠŠå½“前子项记录到 Map,作为以后更深层级的父项查找依据
            //  åŒä¸€çˆ¶é¡¹ä¸‹çš„同名子项不需要重复记录
            treePathMap.put(childKey, node.getId());
        // 1. æŒ‰çˆ¶é¡¹ç¼–码分组
        Map<String, List<BomImportDto>> parentMap = list.stream()
                .filter(bom -> StringUtils.isNotBlank(bom.getParentCode()))
                .collect(Collectors.groupingBy(BomImportDto::getParentCode));
        // 2. éåŽ†æ‰€æœ‰çˆ¶é¡¹ï¼Œé€’å½’ä¿å­˜
        for (Map.Entry<String, List<BomImportDto>> entry : parentMap.entrySet()) {
            //  åˆ›å»º BOM æ•°æ®
            BomImportDto first = entry.getValue().get(0);
            ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec());
            ProductBom bom = new ProductBom();
            bom.setProductModelId(rootModel.getId());
            bom.setVersion("1.0");
            productBomMapper.insert(bom);
            bom.setBomNo("BM." + String.format("%05d", bom.getId()));
            productBomMapper.updateById(bom);
            // å¤„理bom子表数据
            List<BomImportDto> children = entry.getValue();
            saveBomRecursive(children,bom,rootModel,processMap);
        }
        return AjaxResult.success("BOM导入成功");
    }
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -3,11 +3,15 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
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.common.enums.FileNameType;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductStructureDto;
@@ -16,14 +20,20 @@
import com.ruoyi.production.service.ProductOrderService;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.service.impl.StockInventoryServiceImpl;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -38,6 +48,9 @@
    @Autowired
    private ProductProcessRouteMapper productProcessRouteMapper;
    @Autowired
    private ProductStructureRecordMapper productStructureRecordMapper;
    @Autowired
    private ProcessRouteItemMapper processRouteItemMapper;
@@ -69,6 +82,9 @@
    @Autowired
    private StockInventoryServiceImpl stockInventoryService;
    @Autowired
    private CommonFileServiceImpl commonFileService;
    @Override
    public IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder) {
        IPage<ProductOrderDto> productOrderDtoIPage = productOrderMapper.pageProductOrder(page, productOrder);
@@ -82,6 +98,9 @@
            if(stockInventoryDtoIPage.getTotal() > 0){
                productOrderDto.setInventoryQuantity(stockInventoryDtoIPage.getRecords().get(0).getQualitity());
            }
            // é™„ä»¶
            productOrderDto.setSalesLedgerFiles(commonFileService.getFileListByBusinessId(productOrderDto.getId()
            , FileNameType.PRODUCT_ORDER.getValue()));
        });
        return productOrderDtoIPage;
    }
@@ -96,46 +115,58 @@
        productProcessRoute.setProductOrderId(productOrder.getId());
        productProcessRoute.setBomId(processRoute.getBomId());
        productProcessRouteMapper.insert(productProcessRoute);
        // ç»‘定生产bom清单
        List<ProductStructureRecord> productStructureDtos = productOrder.getProductStructureRecords();
        productStructureDtos.forEach(item ->{
            item.setProductOrderId(productOrder.getId());
            productStructureRecordMapper.insert(item);
        });
        //新增生产订单下的工艺路线子表
        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
        List<ProductProcessRouteItem> processRouteItems = productOrder.getProcessRouteItems();
        // ç”Ÿæˆå½“前日期的前缀:年月日
        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        for (ProcessRouteItem processRouteItem : processRouteItems) {
            ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
            productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
            productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
        for (ProductProcessRouteItem productProcessRouteItem : processRouteItems) {
            productProcessRouteItem.setProductModelId(productOrder.getProductModelId());
            productProcessRouteItem.setProductOrderId(productOrder.getId());
            productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
            productProcessRouteItem.setDragSort(processRouteItem.getDragSort());
            int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
            if (insert > 0) {
                // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
                ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectMax(datePrefix);
                int sequenceNumber = 1; // é»˜è®¤åºå·
                if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
                    String lastNo = lastWorkOrder.getWorkOrderNo().toString();
                    if (lastNo.startsWith(datePrefix)) {
                        String seqStr = lastNo.substring(datePrefix.length());
                        try {
                            sequenceNumber = Integer.parseInt(seqStr) + 1;
                        } catch (NumberFormatException e) {
                            sequenceNumber = 1;
                        }
                    }
                }
                // ç”Ÿæˆå®Œæ•´çš„工单号
                String workOrderNoStr = "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
                String workOrderNoStr = getWorkOrderNoStr(lastWorkOrder, datePrefix); // å·¥å•号
                ProductWorkOrder productWorkOrder = new ProductWorkOrder();
                productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
                productWorkOrder.setProductOrderId(productOrder.getId());
                ProductOrder order = productOrderMapper.selectById(productOrder.getId());
                productWorkOrder.setPlanQuantity(order.getQuantity());
                productWorkOrder.setWorkOrderNo(workOrderNoStr);
                productWorkOrder.setPlanStartTime(productProcessRouteItem.getPlanStartTime());
                productWorkOrder.setPlanEndTime(productProcessRouteItem.getPlanEndTime());
                productWorkOrder.setStatus(1);
                productWorkOrder.setUserPower(productProcessRouteItem.getUserPower());
                productWorkOrderMapper.insert(productWorkOrder);
            }
        }
        return productOrderMapper.updateById(productOrder);
    }
    @NotNull
    private static String getWorkOrderNoStr(ProductWorkOrder lastWorkOrder, String datePrefix) {
        int sequenceNumber = 1; // é»˜è®¤åºå·
        if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
            String lastNo = lastWorkOrder.getWorkOrderNo();
            if (lastNo.startsWith(datePrefix)) {
                String seqStr = lastNo.substring(datePrefix.length());
                try {
                    sequenceNumber = Integer.parseInt(seqStr) + 1;
                } catch (NumberFormatException e) {
                    sequenceNumber = 1;
                }
            }
        }
        // ç”Ÿæˆå®Œæ•´çš„工单号
        String workOrderNoStr = "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
        return workOrderNoStr;
    }
    @Override
@@ -149,20 +180,24 @@
    }
    @Override
    public Boolean addProductOrder(ProductOrder productOrder) {
    public Boolean addProductOrder(ProductOrder productOrder) throws IOException {
        String string = generateNextOrderNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        productOrder.setNpsNo(string);
        productOrder.setCompleteQuantity(BigDecimal.ZERO);
        productOrder.setStatus("待生产");
        this.save(productOrder);
        if (ObjectUtils.isNotEmpty(productOrder.getRouteId())) {
            this.bindingRoute(productOrder);
        }
        if(CollectionUtils.isNotEmpty(productOrder.getTempFileIds())){
            commonFileService.migrateTempFilesToFormal(productOrder.getId(), productOrder.getTempFileIds());
        }
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long[] ids) {
        //批量查询productOrder
        List<ProductOrder> productOrders = productOrderMapper.selectList(
                new LambdaQueryWrapper<ProductOrder>()
@@ -247,10 +282,42 @@
            // æ‰¹é‡åˆ é™¤productOrder
            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
                    .in(ProductOrder::getId, ids));
            // åˆ é™¤é™„ä»¶
            commonFileService.deleteByBusinessIds(Arrays.asList(ids), FileNameType.PRODUCT_ORDER.getValue());
            // åˆ é™¤ç”Ÿäº§è®¢å•-物料清单
            productStructureRecordMapper.delete(new LambdaQueryWrapper<ProductStructureRecord>()
                    .in(ProductStructureRecord::getProductOrderId, ids));
        }
        return true;
    }
    @Override
    public Object startOrPause(ProductOrderDto item) {
        ProductOrder productOrder = productOrderMapper.selectById(item.getId());
        if(productOrder == null){
            throw new ServiceException("生产订单不存在");
        }
        int i;
        if(item.getOperation().equals(1)){
            i = 2;
        } else {
            i = 1;
        }
        productOrder.setStatus(item.getOperation() == 1 ? "生产中" : "待生产");
        productOrderMapper.updateById(productOrder);
        List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(new LambdaQueryWrapper<ProductWorkOrder>()
                .eq(ProductWorkOrder::getProductOrderId, productOrder.getId()));
        if(CollectionUtils.isNotEmpty(productWorkOrders)){
            productWorkOrders.forEach(productWorkOrder -> {
                productWorkOrder.setStatus(i);
                productWorkOrderMapper.updateById(productWorkOrder);
            });
        }
        return "操作成功";
    }
    //获取当前生产订单号
    public String getMaxOrderNoByDate(String datePrefix) {
        QueryWrapper<ProductOrder> queryWrapper = new QueryWrapper<>();
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java
@@ -8,6 +8,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * <p>
 *  æœåŠ¡å®žçŽ°ç±»
@@ -23,7 +25,7 @@
    private ProductProcessRouteMapper productProcessRouteMapper;
    @Override
    public ProcessRouteDto listMain(Long orderId) {
    public List<ProcessRouteDto> listMain(Long orderId) {
        return productProcessRouteMapper.listMain(orderId);
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductProcessServiceImpl.java
@@ -9,6 +9,7 @@
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.ProductProcessDto;
import com.ruoyi.production.dto.SysDeptAndUserDto;
import com.ruoyi.production.mapper.ProcessRouteItemMapper;
import com.ruoyi.production.mapper.ProductProcessMapper;
import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
@@ -16,12 +17,18 @@
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.pojo.ProductProcessRouteItem;
import com.ruoyi.production.service.ProductProcessService;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
@Service
@@ -32,6 +39,13 @@
    private ProcessRouteItemMapper processRouteItemMapper;
    @Autowired
    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserDeptMapper sysUserDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Override
    public IPage<ProductProcessDto> listPage(Page page, ProductProcessDto productProcessDto) {
@@ -89,4 +103,61 @@
        productProcessMapper.deleteBatchIds(ids);
        return null;
    }
    public List<SysDeptAndUserDto> listDeptUserTree() {
       return buildDeptUserTree();
    }
    /**
     * æž„建完整的部门-用户树形结构
     */
    public List<SysDeptAndUserDto> buildDeptUserTree() {
        // 1. æŸ¥è¯¢æ‰€æœ‰æ ¹éƒ¨é—¨ï¼ˆparent_id = 0)
        List<SysDeptAndUserDto> rootDeptList = sysDeptMapper.selectChildrenDeptByParentId(0L);
        // 2. é€’归构建每个根部门的子节点,并挂载用户
        for (SysDeptAndUserDto rootDept : rootDeptList) {
            buildChildrenDept(rootDept);
            loadDeptUser(rootDept);
        }
        return rootDeptList;
    }
    /**
     * é€’归构建子部门
     */
    private void buildChildrenDept(SysDeptAndUserDto parentDept) {
        // æŸ¥è¯¢å½“前部门的子部门
        List<SysDeptAndUserDto> childrenDept = sysDeptMapper.selectChildrenDeptByParentId(parentDept.getDeptId());
        if (childrenDept == null || childrenDept.isEmpty()) {
            parentDept.setChildrenList(new ArrayList<>());
            return;
        }
        // ä¸ºæ¯ä¸ªå­éƒ¨é—¨é€’归构建下级,并挂载用户
        for (SysDeptAndUserDto childDept : childrenDept) {
            buildChildrenDept(childDept);
            loadDeptUser(childDept);
        }
        parentDept.setChildrenList(childrenDept);
    }
    /**
     * ä¸ºéƒ¨é—¨åŠ è½½å…³è”çš„ç”¨æˆ·
     */
    private void loadDeptUser(SysDeptAndUserDto dept) {
        // æŸ¥è¯¢éƒ¨é—¨å…³è”的用户ID
        List<Long> userIdList = sysUserDeptMapper.selectUserIdByDeptId(dept.getDeptId());
        if (userIdList == null || userIdList.isEmpty()) {
            dept.setUserList(new ArrayList<>());
            return;
        }
        // æ ¹æ®ç”¨æˆ·ID查询用户信息
        List<SysUser> userList = sysUserMapper.selectUserListByIds(userIdList);
        dept.setUserList(userList);
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductStructureRecordServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.production.service.impl;
import com.ruoyi.production.pojo.ProductStructureRecord;
import com.ruoyi.production.mapper.ProductStructureRecordMapper;
import com.ruoyi.production.service.ProductStructureRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * ç”Ÿäº§è®¢å•-物料清单表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-26 10:34:23
 */
@Service
public class ProductStructureRecordServiceImpl extends ServiceImpl<ProductStructureRecordMapper, ProductStructureRecord> implements ProductStructureRecordService {
}
src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
@@ -129,9 +129,11 @@
    }
    @Override
    public List<ProductStructureDto> listBybomId(Integer bomId) {
        List<ProductStructureDto> list = productStructureMapper.listBybomId(bomId);
        List<ProductStructureDto> list = productStructureMapper.listBybomId(bomId,false);
        Map<Long, ProductStructureDto> map = new HashMap<>();
        for (ProductStructureDto node : list) {
@@ -154,4 +156,9 @@
        return tree;
    }
    @Override
    public List<ProductStructureDto> listBybomIdIsParent(Integer bomId) {
        return productStructureMapper.listBybomId(bomId,true);
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -97,6 +98,13 @@
        if (productProcessRouteItem == null) {
            throw new RuntimeException("工艺路线项不存在");
        }
        // èŽ·å–è®¢å•çš„å·²å®Œæˆå·¥å•
        List<ProductWorkOrder> productWorkOrderList = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery()
                .eq(ProductWorkOrder::getProductOrderId, productProcessRouteItem.getProductOrderId())
                .eq(ProductWorkOrder::getStatus, 3));
        if(CollectionUtils.isEmpty(productWorkOrderList)){
            productWorkOrderList = new ArrayList<>();
        }
        //当前具体工序
        ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId());
        //工艺路线中当前工序对应的产出规格型号
@@ -150,7 +158,7 @@
            ProductionProductInput productionProductInput = new ProductionProductInput();
            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
            productionProductInput.setQuantity(dto.getQuantity());
            productionProductInput.setProductMainId(productionProductMain.getId());
            productionProductInputMapper.insert(productionProductInput);
            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
@@ -173,7 +181,7 @@
                //对应的过程检或者出厂检
                int inspectType = 1;
                String process = productProcess.getName();//工序
                if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
                if (productWorkOrderList.size() == productProcessRouteItems.size() - 1) {
                    //最后一道工序生成出厂检
                    inspectType = 2;
                    process = null;
@@ -214,21 +222,25 @@
            productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
            if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
                productWorkOrder.setActualStartTime(LocalDate.now());//实际开始时间
                productWorkOrder.setStatus(2);
            }
            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
                productWorkOrder.setActualEndTime(LocalDate.now());//实际结束时间
                productWorkOrder.setStatus(3);
            }
            productWorkOrderMapper.updateById(productWorkOrder);
            //生产订单
            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
            if (ObjectUtils.isNull(productOrder.getStartTime())) {
                productOrder.setStartTime(LocalDateTime.now());//开始时间
                productOrder.setStatus("生产中");
            }
            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
            if (productWorkOrderList.size() == productProcessRouteItems.size() - 1) {
                //如果是最后一道工序报工之后生产订单完成数量+
                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
                    productOrder.setEndTime(LocalDateTime.now());//结束时间
                    productOrder.setStatus("已完成");
                }
            }
            productOrderMapper.updateById(productOrder);
src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java
@@ -2,6 +2,7 @@
import java.util.List;
import com.ruoyi.production.dto.SysDeptAndUserDto;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.ruoyi.project.system.domain.SysDept;
@@ -125,4 +126,14 @@
     * @return
     */
    Long maxLevelDeptId(Long deptId);
    /**
     * æŸ¥è¯¢æ‰€æœ‰æœ‰æ•ˆéƒ¨é—¨ï¼ˆæœªåˆ é™¤ã€çŠ¶æ€æ­£å¸¸ï¼‰
     */
    List<SysDeptAndUserDto> selectAllDept();
    /**
     * æ ¹æ®éƒ¨é—¨ID查询子部门
     */
    List<SysDeptAndUserDto> selectChildrenDeptByParentId(@Param("parentId") Long parentId);
}
src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -12,4 +12,9 @@
public interface SysUserDeptMapper extends BaseMapper<SysUserDept> {
    List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo);
    /**
     * æ ¹æ®éƒ¨é—¨ID查询关联的用户ID列表
     */
    List<Long> selectUserIdByDeptId(@Param("deptId") Long deptId);
}
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
@@ -156,4 +156,9 @@
    List<Long> getUserByRole(@Param("role") String role);
    List<Long> getUserByPerms(@Param("perms") List<String> perms);
    /**
     * æ ¹æ®ç”¨æˆ·ID列表查询用户信息
     */
    List<SysUser> selectUserListByIds(@Param("userIds") List<Long> userIds);
}
src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.sales.mapper.CommonFileMapper;
@@ -138,13 +139,6 @@
            Path formalFilePath = formalDirPath.resolve(formalFilename);
            try {
                // æ‰§è¡Œæ–‡ä»¶è¿ç§»ï¼ˆä½¿ç”¨åŽŸå­æ“ä½œç¡®ä¿å®‰å…¨æ€§ï¼‰
//                Files.move(
//                        Paths.get(tempFile.getTempPath()),
//                        formalFilePath,
//                        StandardCopyOption.REPLACE_EXISTING,
//                        StandardCopyOption.ATOMIC_MOVE
//                );
                // åŽŸå­ç§»åŠ¨å¤±è´¥ï¼Œä½¿ç”¨å¤åˆ¶+删除
                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -499,7 +499,7 @@
        if (processRoute == null) {
            return R.fail("请先设置工艺路线");
        }
        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomId(processRoute.getBomId());
        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomId(processRoute.getBomId(),false);
        if (productStructureDtos.isEmpty()) {
            return R.fail("请先设置产品结构");
        }
src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -113,9 +113,12 @@
               pm.model as  model,
               pm.unit as unit,
               pm.drawing_number as drawingNumber,
               pm.product_type as productType
               pm.product_type as productType,
               pr.id as routeId,
               pr.process_route_name as routeName
        from product_model pm
                 left join product p on p.id = pm.product_id
                left join product p on p.id = pm.product_id
                left join process_route pr on pr.id = pm.route_id
        <where>
            <if test="req.productName != null and req.productName != ''">
                and p.product_name like concat('%',#{req.productName},'%')
src/main/resources/mapper/production/ProcessRouteItemMapper.xml
@@ -22,7 +22,8 @@
               pm.model,
               p.product_name,
               pm.unit,
               pm.drawing_number
               pm.drawing_number,
               pp.user_power
        from
            process_route_item pri
                left join product_model pm on pri.product_model_id = pm.id
src/main/resources/mapper/production/ProcessRouteMapper.xml
@@ -13,8 +13,10 @@
    </resultMap>
    <select id="pageProcessRouteDto" resultType="com.ruoyi.production.dto.ProcessRouteDto">
        select ps.*, p.product_name,pm.product_id,pm.model,pb.bom_no,pm.drawing_number
        select ps.*, p.product_name,pm.product_id,pm.model,pb.bom_no,pm.drawing_number,group_concat(pp.name) as processName
        from process_route ps
        left join process_route_item ppi on ps.id = ppi.route_id
        left join product_process pp on ppi.process_id = pp.id
        left join product_bom pb on ps.bom_id = pb.id
        left join product_model pm on ps.product_model_id = pm.id
        left join product p on pm.product_id = p.id
@@ -22,7 +24,17 @@
            <if test="c.model != null and c.model != ''">
                and pm.model like concat('%',#{c.model},'%')
            </if>
            <if test="c.processRouteCode != null and c.processRouteCode != ''">
                and ps.process_route_code like concat('%',#{c.processRouteCode},'%')
            </if>
            <if test="c.processRouteName != null and c.processRouteName != ''">
                and ps.process_route_name like concat('%',#{c.processRouteName},'%')
            </if>
            <if test="c.processName != null and c.processName != ''">
                and pp.name like concat('%',#{c.processName},'%')
            </if>
        </where>
        group by ps.id
        order by ps.id asc
    </select>
</mapper>
src/main/resources/mapper/production/ProductBomMapper.xml
@@ -25,10 +25,13 @@
        left join product p on pm.product_id = p.id)A
        where 1=1
        <if test="c.productModelName != null">
            and productModelName = #{c.productModelName}
            and product_model_name = #{c.productModelName}
        </if>
        <if test="c.productModelId != null">
            and product_model_id = #{c.productModelId}
        </if>
        <if test="c.productName != null">
            and productName = #{c.productName}
            and product_name = #{c.productName}
        </if>
        <if test="c.bomNo != null">
            and bom_no = #{c.bomNo}
src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -77,23 +77,21 @@
               ps.product_model_id,
               ps.process_id,
               ps.unit_quantity,
               ps.unit_quantity * po.quantity as demandedQuantity,
               ps.demanded_quantity as demandedQuantity,
               ps.unit,
               p.product_name,
               pm.drawing_number,
               pp.name as  process_name,
               pm.product_id,
               pm.model,
               pb.bom_no
               pm.model
        from
            product_structure ps
            product_structure_record ps
                left join product_model pm on ps.product_model_id = pm.id
                left join product p on pm.product_id = p.id
                left join product_process pp on ps.process_id = pp.id
                left join product_bom pb on ps.bom_id = pb.id
                left join product_process_route ppr on ps.bom_id = ppr.bom_id
                left join product_order po on po.id = ppr.product_order_id
        where ppr.product_order_id = #{orderId}
        where ps.product_order_id = #{orderId}
        order by ps.id
    </select>
src/main/resources/mapper/production/ProductProcessRouteMapper.xml
@@ -15,12 +15,15 @@
        <result column="product_order_id" property="productOrderId"/>
    </resultMap>
    <select id="listMain" resultType="com.ruoyi.production.dto.ProcessRouteDto">
        select ppr.*, p.product_name, pm.product_id, pm.model, pb.bom_no,pm.drawing_number
        select ppr.*, p.product_name, pm.product_id, pm.model, pb.bom_no,pm.drawing_number,pp.name as processName
        from product_process_route ppr
                 left join product_process_route_item ppri on ppr.id = ppri.product_route_id
                 left join product_process pp on pp.id = ppri.process_id
                 left join product_bom pb on ppr.bom_id = pb.id
                 left join product_model pm on ppr.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
        where ppr.product_order_id = #{orderId}
        group by ppri.id
    </select>
</mapper>
src/main/resources/mapper/production/ProductStructureMapper.xml
@@ -26,6 +26,9 @@
                left join product_bom pb on ps.bom_id = pb.id
                left join product_process pp on ps.process_id = pp.id
        where ps.bom_id = #{bomId}
        <if test="isParent">
           and ps.parent_id is not null
        </if>
        order by ps.id
    </select>
    <select id="listBybomAndProcess" resultType="com.ruoyi.production.dto.ProductStructureDto">
@@ -36,12 +39,11 @@
               pm.model,
               pm.drawing_number
        from
            product_structure ps
            product_structure_record ps
                left join product_model pm on ps.product_model_id = pm.id
                left join product p on pm.product_id = p.id
                left join product_process pp on ps.process_id = pp.id
        where ps.bom_id = #{bomId}
        and ps.process_id=#{processId}
        where ps.process_id=#{processId}
        order by ps.id
    </select>
</mapper>
src/main/resources/mapper/production/ProductStructureRecordMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.production.mapper.ProductStructureRecordMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductStructureRecord">
        <id column="id" property="id" />
        <result column="parent_id" property="parentId" />
        <result column="product_model_id" property="productModelId" />
        <result column="product_order_id" property="productOrderId" />
        <result column="process_id" property="processId" />
        <result column="unit_quantity" property="unitQuantity" />
        <result column="demanded_quantity" property="demandedQuantity" />
        <result column="unit" property="unit" />
        <result column="tenant_id" property="tenantId" />
        <result column="bom_id" property="bomId" />
    </resultMap>
</mapper>
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -39,7 +39,7 @@
        LEFT JOIN product_process pp ON pp.id = ppri.process_id
        LEFT JOIN product_model pm ON pm.id = ppri.product_model_id
        LEFT JOIN product p ON p.id = pm.product_id
        where 1=1
        where pwo.status != 1
            <if test="c.workOrderNo != null and c.workOrderNo != ''">
               and pwo.work_order_no like concat('%',#{c.workOrderNo},'%')
            </if>
src/main/resources/mapper/system/SysDeptMapper.xml
@@ -183,5 +183,19 @@
        FROM DepartmentHierarchy
        WHERE parent_id = 100;
    </select>
    <select id="selectAllDept" resultType="com.ruoyi.production.dto.SysDeptAndUserDto">
        SELECT dept_id, parent_id, ancestors, dept_name, order_num, leader, phone, email,
               status, del_flag, create_by, create_time, update_by, update_time, dept_nick
        FROM sys_dept
        WHERE del_flag = '0' AND status = '0'
        ORDER BY order_num ASC
    </select>
    <select id="selectChildrenDeptByParentId" resultType="com.ruoyi.production.dto.SysDeptAndUserDto">
        SELECT dept_id, parent_id, ancestors, dept_name, order_num, leader, phone, email,
               status, del_flag, create_by, create_time, update_by, update_time, dept_nick
        FROM sys_dept
        WHERE parent_id = #{parentId} AND del_flag = '0' AND status = '0'
        ORDER BY order_num ASC
    </select>
</mapper> 
src/main/resources/mapper/system/SysUserDeptMapper.xml
@@ -24,4 +24,7 @@
            </if>
        </where>
    </select>
    <select id="selectUserIdByDeptId" resultType="java.lang.Long">
        SELECT user_id FROM sys_user_dept WHERE dept_id = #{deptId}
    </select>
</mapper>
src/main/resources/mapper/system/SysUserMapper.xml
@@ -297,5 +297,16 @@
            )
        </if>
    </select>
    <select id="selectUserListByIds" resultType="com.ruoyi.project.system.domain.SysUser">
        SELECT user_id, user_name, nick_name, user_type, email, phonenumber, sex, avatar,
        password, status, del_flag, login_ip, login_date, create_by, create_time,
        update_by, update_time, remark, tenant_id
        FROM sys_user
        WHERE user_id IN
        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
            #{userId}
        </foreach>
        AND del_flag = '0' AND status = '0'
    </select>
</mapper>