zss
2 天以前 c145f0e2c2a4a301f11c8b4c132f50c8a56bec62
生产订单重构
已添加6个文件
已修改20个文件
872 ■■■■ 文件已修改
src/main/java/com/ruoyi/common/config/MybatisHandler.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductProcessRouteController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductProcessRouteItemController.java 184 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductOrderMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrder.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductProcessRouteItemService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProcessRouteItemServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteItemServiceImpl.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMapper.xml 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/MybatisHandler.java
@@ -18,7 +18,6 @@
            tenantId = SecurityUtils.getLoginUser().getTenantId();
        } catch (Exception ignored) {
        }
        System.out.println("执行插入填充...");
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime",  LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "createUser", Integer.class, userId);
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -514,9 +514,9 @@
        List<ProductOrderDto> productOrderDtoList = new ArrayList<>();
        productOrderList.forEach(productOrder -> {
            ProductOrderDto productOrderDto = productOrderMapper.productMainByOrderId(productOrder);
            if (productOrderDto != null && productOrderDto.getPlanQuantity() != null && productOrderDto.getQuantity() != null) {
                productOrderDto.setCompletionStatus(BigDecimal.valueOf(productOrderDto.getPlanQuantity()-productOrderDto.getQuantity()).divide(BigDecimal.valueOf(productOrderDto.getPlanQuantity()), 2, RoundingMode.HALF_UP));
            }
//            if (productOrderDto != null && productOrderDto.getPlanQuantity() != null && productOrderDto.getQuantity() != null) {
//                productOrderDto.setCompletionStatus((productOrderDto.getPlanQuantity().subtract(productOrderDto.getQuantity())).divide(productOrderDto.getPlanQuantity(), 2, RoundingMode.HALF_UP));
//            }
            productOrderDtoList.add(productOrderDto);
        });
        productionProgressDto.setCompletedOrderDetails(productOrderDtoList);
@@ -525,7 +525,7 @@
        // 2. åˆå§‹åŒ–汇总数据
        int totalCount = productOrderDtoIPage.getRecords().size();
        int completedCount = (int) productOrderDtoIPage.getRecords().stream().map(productOrderDto -> productOrderMapper.productMainByOrderId(productOrderDto)).filter(productOrderDto1 -> productOrderDto1.getQuantity() != null && productOrderDto1.getQuantity() == 0).count();
        int completedCount = (int) productOrderDtoIPage.getRecords().stream().map(productOrderDto -> productOrderMapper.productMainByOrderId(productOrderDto)).filter(productOrderDto1 -> productOrderDto1.getQuantity() != null && productOrderDto1.getQuantity().compareTo(BigDecimal.ZERO) == 0).count();
        // 6. èµ‹å€¼æ±‡æ€»æ•°æ®
        productionProgressDto.setTotalOrderCount(totalCount);
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -1,18 +1,26 @@
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;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RequestMapping("productOrder")
@RestController
@Api(tags = "生产订单")
public class ProductOrderController {
    @Autowired
@@ -25,6 +33,28 @@
        return R.ok(productOrderService.pageProductOrder(page, productOrder));
    }
    @ApiOperation("绑定工艺路线")
    @PostMapping("/bindingRoute")
    public R bindingRoute(@RequestBody ProductOrder productOrder) {
        return R.ok(productOrderService.bindingRoute(productOrder));
    }
    @ApiOperation("查询规格型号对应的工艺路线")
    @GetMapping("/listProcessRoute")
    public R listProcessRoute(Long productModelId) {
        return R.ok(productOrderService.listProcessRoute(productModelId));
    }
    /**
     * å¯¼å‡ºç”Ÿäº§è®¢å•
     */
    @Log(title = "生产订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ProductOrderDto productOrderDto) {
        List<ProductOrderDto> list;
        list = productOrderService.pageProductOrder(new Page<>(1, -1), productOrderDto).getRecords();
        ExcelUtil<ProductOrderDto> util = new ExcelUtil<ProductOrderDto>(ProductOrderDto.class);
        util.exportExcel(response, list, "生产订单数据");
    }
}
src/main/java/com/ruoyi/production/controller/ProductProcessRouteController.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-01-15 02:51:09
 */
@RestController
@RequestMapping("/productProcessRoute")
public class ProductProcessRouteController {
}
src/main/java/com/ruoyi/production/controller/ProductProcessRouteItemController.java
@@ -2,11 +2,13 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductProcessRouteItemDto;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductProcessRouteItemService;
import com.ruoyi.production.service.ProductProcessRouteService;
import com.ruoyi.production.service.ProductWorkOrderService;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
@@ -34,175 +36,43 @@
@Api(tags = "生产工艺路线")
public class ProductProcessRouteItemController {
    private final ProductOrderMapper productOrderMapper;
    private ProductProcessRouteItemService productProcessRouteItemService;
    private ProductWorkOrderService productWorkOrderService;
    private ProductWorkOrderMapper productWorkOrderMapper;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    private ProductionProductMainMapper productionProductMainMapper;
    private ProductionProductInputMapper productionProductInputMapper;
    private ProductionProductOutputMapper productionProductOutputMapper;
    private QualityInspectMapper qualityInspectMapper;
    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private ProductProcessRouteService productProcessRouteService;
    @GetMapping("list")
    @ApiOperation("根据Id查询工艺项目")
    @ApiOperation("根据Id查询工艺路线子表")
    public R list(Long orderId) {
        return R.ok(productProcessRouteItemService.listItem(orderId));
    }
    @GetMapping("listMain")
    @ApiOperation("根据Id查询工艺路线主表")
    public R listMain(Long orderId) {
        return R.ok(productProcessRouteService.listMain(orderId));
    }
    @PostMapping("/addRouteItem")
    @ApiOperation("新增生产订单的工艺路线详情")
    public R addRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
        return productProcessRouteItemService.addRouteItem(productProcessRouteItem);
    }
    @PostMapping("/updateRouteItem")
    @ApiOperation("批量新增修改")
    @Transactional(rollbackFor = Exception.class)
    public R addOrUpdate(@RequestBody ProductProcessRouteItemDto processRouteItemDto) {
        ProductOrder productOrder = productOrderMapper.selectById(processRouteItemDto.getRouteId());
        if (productOrder == null) {
            return R.fail("未找到ID为[" + processRouteItemDto.getRouteId() + "]的产品订单");
        }
        SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectOne(new LambdaQueryWrapper<SalesLedgerProduct>()
                .eq(SalesLedgerProduct::getSalesLedgerId, productOrder.getSalesLedgerId()));
        if (salesLedgerProduct == null) {
            return R.fail("未找到销售台账ID为[" + productOrder.getSalesLedgerId() + "]的台账产品");
    @ApiOperation("修改生产订单的工艺路线详情")
    public R updateRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
        return R.ok(productProcessRouteItemService.updateById(productProcessRouteItem));
        }
        List<ProductProcessRouteItem> items = processRouteItemDto.getProcessRouteItem();
        if (CollectionUtils.isEmpty(items)) {
            return R.ok();
        }
        Map<Boolean, List<ProductProcessRouteItem>> partitioned = items.stream()
                .collect(Collectors.partitioningBy(
                        item -> item.getId() != null && item.getId() > 0
                ));
        List<ProductProcessRouteItem> toUpdate = partitioned.get(true);
        List<ProductProcessRouteItem> toInsert = partitioned.get(false);
        // æ‰¹é‡å¤„理
        boolean result = true;
        if (!toInsert.isEmpty()) {
            result = productProcessRouteItemService.saveBatch(toInsert);
            if (result) {
                // ç”Ÿæˆå·¥å•号
                String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                // æŸ¥è¯¢ä»Šæ—¥æœ€å¤§å·¥å•号
                QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.likeRight("work_order_no", datePrefix)
                        .select("MAX(work_order_no) as maxNo");
                List<Map<String, Object>> maxNoList = productWorkOrderMapper.selectMaps(queryWrapper);
                String maxWorkOrderNo = null;
                if (!maxNoList.isEmpty() && maxNoList.get(0) != null && maxNoList.get(0).get("maxNo") != null) {
                    maxWorkOrderNo = maxNoList.get(0).get("maxNo").toString();
                }
                int startSequence = 1;
                if (maxWorkOrderNo != null && maxWorkOrderNo.startsWith(datePrefix)) {
                    try {
                        String seqStr = maxWorkOrderNo.substring(datePrefix.length());
                        startSequence = Integer.parseInt(seqStr) + 1;
                    } catch (NumberFormatException e) {
                        startSequence = 1;
                    }
                }
                // æ‰¹é‡ç”Ÿæˆå·¥å•
                List<ProductWorkOrder> workOrders = new ArrayList<>();
                for (int i = 0; i < toInsert.size(); i++) {
                    ProductProcessRouteItem item = toInsert.get(i);
                    String workOrderNoStr = String.format("%s%03d", datePrefix, startSequence + i);
                    ProductWorkOrder workOrder = new ProductWorkOrder();
                    workOrder.setProductProcessRouteItemId(item.getId());
                    workOrder.setProductOrderId(item.getRouteId());
                    workOrder.setWorkOrderNo(workOrderNoStr);
                    workOrder.setPlanQuantity(salesLedgerProduct.getQuantity());
                    workOrder.setStatus(1);
                    workOrders.add(workOrder);
                }
                result = productWorkOrderService.saveBatch(workOrders);
            }
        }
        if (!toUpdate.isEmpty()) {
            result = productProcessRouteItemService.updateBatchById(toUpdate) && result;
        }
        return R.ok(result);
    }
    @DeleteMapping("/deleteRouteItem")
    @DeleteMapping("/deleteRouteItem/{id}")
    @ApiOperation("删除生产工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R deleteRouteItem(@RequestBody ProductProcessRouteItemDto processRouteItemDto) {
        if (processRouteItemDto == null || processRouteItemDto.getId() == null) {
            return R.fail("删除失败:工艺路线项ID不能为空");
        }
        Long routeItemId = processRouteItemDto.getId();
        try {
            // æŸ¥è¯¢å·¥å•
            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectOne(
                    new LambdaQueryWrapper<ProductWorkOrder>()
                            .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId)
                            .last("LIMIT 1")
            );
            if (productWorkOrder == null) {
                return R.fail("删除失败:未找到关联的生产工单");
            }
            Long workOrderId = productWorkOrder.getId();
            Long productOrderId = productWorkOrder.getProductOrderId();
            // æŸ¥è¯¢ç”Ÿäº§ä¸»è¡¨
            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(
                    new LambdaQueryWrapper<ProductionProductMain>()
                            .eq(ProductionProductMain::getWorkOrderId, workOrderId)
            );
            if (!productionProductMains.isEmpty()) {
                // æ‰¹é‡åˆ é™¤å­è¡¨
                for (ProductionProductMain main : productionProductMains) {
                    Long mainId = main.getId();
                    // åˆ é™¤æŠ•å…¥
                    productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                            .eq(ProductionProductInput::getProductMainId, mainId));
                    // åˆ é™¤äº§å‡º
                    productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
                            .eq(ProductionProductOutput::getProductMainId, mainId));
                    // åˆ é™¤è´¨æ£€
                    qualityInspectMapper.delete(new LambdaQueryWrapper<QualityInspect>()
                            .eq(QualityInspect::getProductMainId, mainId));
                }
    public R deleteRouteItem(@PathVariable("id") Long id) {
        return productProcessRouteItemService.deleteRouteItem(id);
            }
            //  åˆ é™¤æŠ¥å·¥ï¼ˆç”Ÿäº§ä¸»è¡¨ï¼‰
            productionProductMainMapper.delete(new LambdaQueryWrapper<ProductionProductMain>()
                    .eq(ProductionProductMain::getWorkOrderId, workOrderId));
            // æŸ¥è¯¢è®¢å• + åˆ é™¤æ ¸ç®—
            ProductOrder productOrder = productOrderMapper.selectById(productOrderId);
            if (productOrder != null && productOrder.getSalesLedgerId() != null) {
                salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
                        .eq(SalesLedgerProductionAccounting::getSalesLedgerId, productOrder.getSalesLedgerId()));
            }
            // åˆ é™¤å…³è”工单
            productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
                    .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId));
            // åˆ é™¤ä¸»è¡¨æ•°æ®
            boolean removeFlag = productProcessRouteItemService.removeById(routeItemId);
            if (!removeFlag) {
                return R.fail("删除失败:工艺路线项主表数据不存在");
            }
            return R.ok();
        } catch (Exception e) {
            return R.fail("删除生产工艺路线失败:" + e.getMessage());
        }
    @PostMapping ("/sortRouteItem")
    @ApiOperation("排序")
    public R sortRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
        return R.ok(productProcessRouteItemService.sortRouteItem(productProcessRouteItem));
    }
}
src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -1,5 +1,7 @@
package com.ruoyi.production.dto;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.production.pojo.ProductOrder;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -7,32 +9,30 @@
import java.math.BigDecimal;
@Data
@ExcelIgnoreUnannotated
public class ProductOrderDto extends ProductOrder {
    @ApiModelProperty(value = "销售合同号")
    @Excel(name = "销售合同号")
    private String salesContractNo;
    @ApiModelProperty(value = "项目名")
    @Excel(name = "项目名")
    private String projectName;
    @ApiModelProperty(value = "客户名")
    @ApiModelProperty(value = "客户名称")
    @Excel(name = "客户名称")
    private String customerName;
    @ApiModelProperty(value = "产品名称")
    @Excel(name = "产品名称")
    private String productCategory;
    @ApiModelProperty(value = "规格")
    @Excel(name = "规格")
    private String specificationModel;
    @ApiModelProperty(value = "计划数量")
    private Integer planQuantity;
    @ApiModelProperty(value = "数量")
    private Integer Quantity;
    @ApiModelProperty(value = "工单号")
    private String workOrderNo;
    @ApiModelProperty(value = "是否报工")
    private Integer reportWork;
    @ApiModelProperty(value = "工单状态")
    private Integer status;
    @ApiModelProperty(value = "订单完成度")
    private BigDecimal completionStatus;
    @ApiModelProperty(value = "工艺路线编号")
    @Excel(name = "工艺路线编号")
    private String processRouteCode;
}
src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java
@@ -23,7 +23,5 @@
    private String productName;
    private List<ProductProcessRouteItem> processRouteItem;
    private String model;
}
src/main/java/com/ruoyi/production/mapper/ProductOrderMapper.java
@@ -4,9 +4,12 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ProductOrderMapper extends BaseMapper<ProductOrder> {
@@ -16,4 +19,6 @@
     * æ ¹æ®è®¢å•ID查询工单报工
     */
     ProductOrderDto productMainByOrderId(@Param("c") ProductOrder productOrder);
    List<ProcessRoute> listProcessRoute(@Param("productModelId") Long productModelId);
}
src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.ruoyi.production.mapper;
import com.ruoyi.production.dto.ProcessRouteDto;
import com.ruoyi.production.pojo.ProductProcessRoute;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
 *  Mapper æŽ¥å£
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-15 02:51:09
 */
@Mapper
public interface ProductProcessRouteMapper extends BaseMapper<ProductProcessRoute> {
    ProcessRouteDto listMain(@Param("orderId") Long orderId);
}
src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
@@ -18,6 +18,7 @@
    private Long id;
    @ApiModelProperty(value = "产品ID")
    //product_model
    private Long productModelId;
    @ApiModelProperty(value = "描述")
@@ -32,7 +33,7 @@
    private LocalDateTime createTime;
    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "工艺路线编码")
src/main/java/com/ruoyi/production/pojo/ProductOrder.java
@@ -1,11 +1,15 @@
package com.ruoyi.production.pojo;
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;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@@ -24,7 +28,7 @@
    private Long salesLedgerId;
    /**
     * é”€å”®å°è´¦äº§å“id
     * é”€å”®å°è´¦äº§å“id(sales_ledger_product)
     */
    @ApiModelProperty(value = "销售台账产品id")
    private Long productModelId;
@@ -39,6 +43,7 @@
     * ç”Ÿäº§è®¢å•号
     */
    @ApiModelProperty(value = "生产订单号")
    @Excel(name = "生产订单号")
    private String npsNo;
    /**
@@ -51,11 +56,45 @@
    //创建时间
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "创建时间")
    private LocalDateTime createTime;
    //修改时间
    @ApiModelProperty(value = "修改时间")
    @TableField(fill = FieldFill.UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    /**
     * éœ€æ±‚数量
     */
    @ApiModelProperty(value = "需求数量")
    @Excel(name = "需求数量")
    private BigDecimal quantity;
    /**
     * å®Œæˆæ•°é‡
     */
    @ApiModelProperty(value = "完成数量")
    @Excel(name = "完成数量")
    private BigDecimal completeQuantity;
    @Excel(name = "开始时间")
    @ApiModelProperty(value = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startTime;
    @ApiModelProperty(value = "结束时间")
    @Excel(name = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime endTime;
}
src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.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.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * <p>
 *
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-15 02:51:09
 */
@Getter
@Setter
@TableName("product_process_route")
@ApiModel(value = "ProductProcessRoute对象", description = "")
public class ProductProcessRoute implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty("产品id")
    //product_model
    private Long productModelId;
    @ApiModelProperty("描述")
    private String description;
    @ApiModelProperty("租户id")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty("录入时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @ApiModelProperty("更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty("关联bom的id")
    private Long bomId;
    @ApiModelProperty("工艺路线编码")
    private String processRouteCode;
    @ApiModelProperty("生产订单的id")
    private Long productOrderId;
}
src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
@@ -14,7 +14,10 @@
    private Long id;
    @ApiModelProperty(value = "生产订单id(product_order_id)")
    private Long routeId;
    private Long productOrderId;
    @ApiModelProperty(value = "生产订单的工艺路线id(product_process_route)")
    private Long productRouteId;
    @ApiModelProperty(value = "工序id")
    private Long processId;
src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
@@ -1,8 +1,10 @@
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.io.Serializable;
import java.math.BigDecimal;
@@ -42,13 +44,17 @@
     */
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    /**
     * ä¿®æ”¹æ—¶é—´
     */
    @ApiModelProperty(value = "修改时间")
    @TableField(fill = FieldFill.UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    /**
@@ -102,20 +108,10 @@
    /**
     * è®¡åˆ’数量
     */
    @ApiModelProperty(value = "计划数量")
    private BigDecimal planQuantity;
    /**
     * å®žé™…数量
     */
    @ApiModelProperty(value = "数量")
    private BigDecimal quantity;
    private BigDecimal planQuantity;
    /**
     * æŠ¥å·¥id
     */
    @ApiModelProperty(value = "报工id")
    private Long productMainId;
}
src/main/java/com/ruoyi/production/service/ProductOrderService.java
@@ -4,10 +4,18 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import java.util.List;
public interface ProductOrderService extends IService<ProductOrder> {
    IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder);
    int bindingRoute(ProductOrder productOrder);
    List<ProcessRoute> listProcessRoute(Long productModelId);
}
src/main/java/com/ruoyi/production/service/ProductProcessRouteItemService.java
@@ -1,6 +1,7 @@
package com.ruoyi.production.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductProcessRouteItemDto;
import com.ruoyi.production.pojo.ProductProcessRouteItem;
@@ -8,4 +9,10 @@
public interface ProductProcessRouteItemService extends IService<ProductProcessRouteItem> {
    List<ProductProcessRouteItemDto> listItem(Long orderId);
    R deleteRouteItem(Long id);
    R addRouteItem(ProductProcessRouteItem productProcessRouteItem);
    int sortRouteItem(ProductProcessRouteItem productProcessRouteItem);
}
src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.production.service;
import com.ruoyi.production.dto.ProcessRouteDto;
import com.ruoyi.production.pojo.ProductProcessRoute;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 *  æœåŠ¡ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-15 02:51:09
 */
public interface ProductProcessRouteService extends IService<ProductProcessRoute> {
    ProcessRouteDto listMain(Long orderId);
}
src/main/java/com/ruoyi/production/service/impl/ProcessRouteItemServiceImpl.java
@@ -37,8 +37,6 @@
        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(Wrappers.<ProcessRouteItem>lambdaQuery()
                .eq(ProcessRouteItem::getRouteId, oldProcessRouteItem.getRouteId())
                .orderByAsc(ProcessRouteItem::getDragSort));
        //查询被更改的那条数据原来是第几条
        int oldIndex = processRouteItems.indexOf(oldProcessRouteItem);
        // èŽ·å–ç›®æ ‡ä½ç½®ï¼ˆç§»åŠ¨åˆ°ç¬¬å‡ ä¸ªä¹‹åŽï¼‰
        Integer targetPosition = processRouteItem.getDragSort();
        if (targetPosition != null && targetPosition >= 0) {
src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -1,22 +1,104 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.mapper.ProductOrderMapper;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProcessRouteService;
import com.ruoyi.production.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Service
public class ProductOrderServiceImpl extends ServiceImpl<ProductOrderMapper, ProductOrder> implements ProductOrderService {
    @Autowired
    private ProductOrderMapper productOrderMapper;
    @Autowired
    private ProcessRouteMapper processRouteMapper;
    @Autowired
    private ProductProcessRouteMapper productProcessRouteMapper;
    @Autowired
    private ProcessRouteItemMapper processRouteItemMapper;
    @Autowired
    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
    @Autowired
    private ProductWorkOrderMapper productWorkOrderMapper;
    @Override
    public IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder) {
        return productOrderMapper.pageProductOrder(page, productOrder);
    }
    @Override
    public int bindingRoute(ProductOrder productOrder) {
        //新增生产订单下的工艺路线主表
        ProcessRoute processRoute = processRouteMapper.selectById(productOrder.getRouteId());
        ProductProcessRoute productProcessRoute = new ProductProcessRoute();
        productProcessRoute.setProductModelId(processRoute.getProductModelId());
        productProcessRoute.setProcessRouteCode(processRoute.getProcessRouteCode());
        productProcessRoute.setProductOrderId(productOrder.getId());
        productProcessRoute.setBomId(processRoute.getBomId());
        productProcessRouteMapper.insert(productProcessRoute);
        //新增生产订单下的工艺路线子表
        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
        // ç”Ÿæˆå½“前日期的前缀:年月日
        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        for (ProcessRouteItem processRouteItem : processRouteItems) {
            ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
            productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
            productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
            productProcessRouteItem.setProductOrderId(productOrder.getId());
            productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
            int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
            if (insert > 0) {
                // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
                QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.likeRight("work_order_no", datePrefix)
                        .orderByDesc("work_order_no")
                        .last("LIMIT 1");
                ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
                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 = String.format("%s%03d", datePrefix, sequenceNumber);
                ProductWorkOrder productWorkOrder = new ProductWorkOrder();
                productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
                productWorkOrder.setProductOrderId(productOrder.getId());
                productWorkOrder.setPlanQuantity(productOrder.getQuantity());
                productWorkOrder.setWorkOrderNo(workOrderNoStr);
                productWorkOrder.setStatus(1);
                productWorkOrderMapper.insert(productWorkOrder);
            }
        }
        return productOrderMapper.updateById(productOrder);
    }
    @Override
    public List<ProcessRoute> listProcessRoute(Long productModelId) {
        return productOrderMapper.listProcessRoute(productModelId);
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteItemServiceImpl.java
@@ -1,23 +1,206 @@
package com.ruoyi.production.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductProcessRouteItemDto;
import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
import com.ruoyi.production.pojo.ProductProcessRouteItem;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductProcessRouteItemService;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import lombok.AllArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class ProductProcessRouteItemServiceImpl extends ServiceImpl<ProductProcessRouteItemMapper, ProductProcessRouteItem> implements ProductProcessRouteItemService {
    @Autowired
    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
    private ProductionProductMainMapper productionProductMainMapper;
    private ProductionProductInputMapper productionProductInputMapper;
    private ProductionProductOutputMapper productionProductOutputMapper;
    private QualityInspectMapper qualityInspectMapper;
    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private ProductWorkOrderMapper productWorkOrderMapper;
    private ProductOrderMapper productOrderMapper;
    private ProductProcessRouteMapper productProcessRouteMapper;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    @Override
    public List<ProductProcessRouteItemDto> listItem(Long orderId) {
        return productProcessRouteItemMapper.listItem(orderId);
    }
    @Override
    public R deleteRouteItem(Long id) {
        Long routeItemId = id;
        try {
            // æŸ¥è¯¢å·¥å•
            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectOne(
                    new LambdaQueryWrapper<ProductWorkOrder>()
                            .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId)
                            .last("LIMIT 1")
            );
            if (productWorkOrder == null) {
                throw new RuntimeException("删除失败:未找到关联的生产工单");
            }
            Long workOrderId = productWorkOrder.getId();
            Long productOrderId = productWorkOrder.getProductOrderId();
            // æŸ¥è¯¢ç”Ÿäº§ä¸»è¡¨
            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(
                    new LambdaQueryWrapper<ProductionProductMain>()
                            .eq(ProductionProductMain::getWorkOrderId, workOrderId)
            );
            if (!productionProductMains.isEmpty()) {
                // æ‰¹é‡åˆ é™¤å­è¡¨
                for (ProductionProductMain main : productionProductMains) {
                    Long mainId = main.getId();
                    // åˆ é™¤æŠ•å…¥
                    productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                            .eq(ProductionProductInput::getProductMainId, mainId));
                    // åˆ é™¤äº§å‡º
                    productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
                            .eq(ProductionProductOutput::getProductMainId, mainId));
                    // åˆ é™¤è´¨æ£€
                    qualityInspectMapper.delete(new LambdaQueryWrapper<QualityInspect>()
                            .eq(QualityInspect::getProductMainId, mainId));
                }
            }
            //  åˆ é™¤æŠ¥å·¥ï¼ˆç”Ÿäº§ä¸»è¡¨ï¼‰
            productionProductMainMapper.delete(new LambdaQueryWrapper<ProductionProductMain>()
                    .eq(ProductionProductMain::getWorkOrderId, workOrderId));
            // æŸ¥è¯¢è®¢å• + åˆ é™¤æ ¸ç®—
            ProductOrder productOrder = productOrderMapper.selectById(productOrderId);
            if (productOrder != null && productOrder.getSalesLedgerId() != null) {
                salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
                        .eq(SalesLedgerProductionAccounting::getSalesLedgerId, productOrder.getSalesLedgerId()));
            }
            // åˆ é™¤å…³è”工单
            productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
                    .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId));
            // åˆ é™¤ä¸»è¡¨æ•°æ®
            ProductProcessRouteItem deleteProductProcessRouteItem = productProcessRouteItemMapper.selectById(routeItemId);
            Long productRouteId = deleteProductProcessRouteItem.getProductRouteId();
            // åˆ é™¤æŒ‡å®šæ•°æ®
            productProcessRouteItemMapper.deleteById(id);
            // æŸ¥è¯¢è¯¥å·¥è‰ºè·¯çº¿çš„æ‰€æœ‰å·¥åºå¹¶æŒ‰ç…§é¡ºåºæŽ’序
            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery()
                    .eq(ProductProcessRouteItem::getProductRouteId, productRouteId)
                    .orderByAsc(ProductProcessRouteItem::getDragSort));
            // é‡æ–°è®¾ç½®æŽ’序值,使序号连续
            for (int i = 0; i < productProcessRouteItems.size(); i++) {
                ProductProcessRouteItem item = productProcessRouteItems.get(i);
                if (!item.getDragSort().equals(i + 1)) {
                    item.setDragSort(i + 1);
                    productProcessRouteItemMapper.updateById(item);
                }
            }
            return R.ok();
        } catch (Exception e) {
            throw new RuntimeException("删除生产工艺路线失败:" + e.getMessage());
        }
    }
    @Override
    public R addRouteItem(ProductProcessRouteItem productProcessRouteItem) {
        ProductOrder productOrder = productOrderMapper.selectById(productProcessRouteItem.getProductOrderId());
        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
        // ç”Ÿæˆå½“前日期的前缀:年月日
        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        if (insert > 0) {
            // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
            QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("work_order_no", datePrefix)
                    .orderByDesc("work_order_no")
                    .last("LIMIT 1");
            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
            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 = String.format("%s%03d", datePrefix, sequenceNumber);
            ProductWorkOrder productWorkOrder = new ProductWorkOrder();
            productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
            productWorkOrder.setProductOrderId(productProcessRouteItem.getProductOrderId());
            productWorkOrder.setPlanQuantity(productOrder.getQuantity());
            productWorkOrder.setWorkOrderNo(workOrderNoStr);
            productWorkOrder.setStatus(1);
            productWorkOrderMapper.insert(productWorkOrder);
        }
        return R.ok();
    }
    @Override
    public int sortRouteItem(ProductProcessRouteItem productProcessRouteItem) {
        //查询被改动的这条数据
        ProductProcessRouteItem oldProductProcessRouteItem = productProcessRouteItemMapper.selectById(productProcessRouteItem.getId());
        //查询该工艺路线的所有工序并按照顺序排序
        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery()
                .eq(ProductProcessRouteItem::getProductRouteId, oldProductProcessRouteItem.getProductRouteId())
                .orderByAsc(ProductProcessRouteItem::getDragSort));
        // èŽ·å–ç›®æ ‡ä½ç½®ï¼ˆç§»åŠ¨åˆ°ç¬¬å‡ ä¸ªä¹‹åŽï¼‰
        Integer targetPosition = productProcessRouteItem.getDragSort();
        if (targetPosition != null && targetPosition >= 0) {
            // ç§»åŠ¨å…ƒç´ åˆ°æ–°çš„ä½ç½®
            productProcessRouteItems.remove(oldProductProcessRouteItem);
            productProcessRouteItems.add(targetPosition-1, oldProductProcessRouteItem);
            // æ›´æ–°æ‰€æœ‰å—影响的排序字段
            for (int i = 0; i < productProcessRouteItems.size(); i++) {
                ProductProcessRouteItem item = productProcessRouteItems.get(i);
                if (!item.getId().equals(oldProductProcessRouteItem.getId())) {
                    // æ£€æŸ¥æ˜¯å¦éœ€è¦æ›´æ–°æŽ’序值
                    if (item.getDragSort() != i+1) {
                        item.setDragSort(i+1);
                        productProcessRouteItemMapper.updateById(item);
                    }
                } else {
                    // æ›´æ–°åŽŸè®°å½•çš„æ–°æŽ’åºä½ç½®
                    oldProductProcessRouteItem.setDragSort(targetPosition);
                    productProcessRouteItemMapper.updateById(oldProductProcessRouteItem);
                }
            }
            return 1;
        }
        return 0;
    }
}
src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.ruoyi.production.service.impl;
import com.ruoyi.production.dto.ProcessRouteDto;
import com.ruoyi.production.pojo.ProductProcessRoute;
import com.ruoyi.production.mapper.ProductProcessRouteMapper;
import com.ruoyi.production.service.ProductProcessRouteService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * <p>
 *  æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-01-15 02:51:09
 */
@Service
public class ProductProcessRouteServiceImpl extends ServiceImpl<ProductProcessRouteMapper, ProductProcessRoute> implements ProductProcessRouteService {
    @Autowired
    private ProductProcessRouteMapper productProcessRouteMapper;
    @Override
    public ProcessRouteDto listMain(Long orderId) {
        return productProcessRouteMapper.listMain(orderId);
    }
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -55,6 +55,7 @@
    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
    private ProcessRouteMapper processRouteMapper;
    private ProductProcessRouteMapper productProcessRouteMapper;
    private ProductWorkOrderMapper productWorkOrderMapper;
@@ -136,7 +137,7 @@
            // æ‰¹é‡æŸ¥è¯¢processRouteItems
            List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList(
                    new LambdaQueryWrapper<ProductProcessRouteItem>()
                            .in(ProductProcessRouteItem::getRouteId, orderIds)
                            .in(ProductProcessRouteItem::getProductOrderId, orderIds)
            );
            if (!CollectionUtils.isEmpty(allRouteItems)) {
@@ -149,9 +150,13 @@
                                .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds));
            }
            // æ‰¹é‡åˆ é™¤processRouteItem
            // æ‰¹é‡åˆ é™¤productProcessRouteItem
            productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
                            .in(ProductProcessRouteItem::getRouteId, orderIds));
                            .in(ProductProcessRouteItem::getProductOrderId, orderIds));
            // æ‰¹é‡åˆ é™¤productProcessRoute
            productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>()
                    .in(ProductProcessRoute::getProductOrderId, orderIds));
            // æ‰¹é‡åˆ é™¤productOrder
            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
@@ -190,10 +195,20 @@
            productOrder.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
            productOrder.setProductModelId(salesLedgerProduct.getId());
            productOrder.setNpsNo("SC" + String.format("%08d", salesLedgerProduct.getId()));
            productOrder.setQuantity(salesLedgerProduct.getQuantity());//需求数量
            productOrder.setCompleteQuantity(BigDecimal.ZERO);//完成数量
            productOrderMapper.insert(productOrder);
            ProcessRoute processRoute = processRouteMapper.selectOne(new QueryWrapper<ProcessRoute>().lambda().eq(ProcessRoute::getProductModelId, salesLedgerProduct.getProductModelId()));
            if (processRoute != null) {
                //新增生产订单工艺路线主表
                ProductProcessRoute productProcessRoute = new ProductProcessRoute();
                productProcessRoute.setProductModelId(processRoute.getProductModelId());
                productProcessRoute.setProcessRouteCode(processRoute.getProcessRouteCode());
                productProcessRoute.setProductOrderId(productOrder.getId());
                productProcessRoute.setBomId(processRoute.getBomId());
                productProcessRouteMapper.insert(productProcessRoute);
                //新增生产订单工艺路线子表
                List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
                // ç”Ÿæˆå½“前日期的前缀:年月日
                String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
@@ -201,7 +216,8 @@
                    ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
                    productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
                    productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
                    productProcessRouteItem.setRouteId(productOrder.getId());
                    productProcessRouteItem.setProductOrderId(productOrder.getId());
                    productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
                    int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
                    if (insert > 0) {
                        // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -96,6 +96,7 @@
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    private final ProductProcessRouteMapper productProcessRouteMapper;
    private final ProcessRouteItemMapper processRouteItemMapper;
@@ -400,7 +401,7 @@
            // æ‰¹é‡æŸ¥è¯¢processRouteItems
            List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList(
                    new LambdaQueryWrapper<ProductProcessRouteItem>()
                            .in(ProductProcessRouteItem::getRouteId, orderIds)
                            .in(ProductProcessRouteItem::getProductOrderId, orderIds)
            );
            if (!CollectionUtils.isEmpty(allRouteItems)) {
@@ -455,7 +456,11 @@
            }
            // æ‰¹é‡åˆ é™¤processRouteItem
            productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
                    .in(ProductProcessRouteItem::getRouteId, orderIds));
                    .in(ProductProcessRouteItem::getProductOrderId, orderIds));
            // æ‰¹é‡åˆ é™¤productProcessRoute
            productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>()
                    .in(ProductProcessRoute::getProductOrderId, orderIds));
            // æ‰¹é‡åˆ é™¤productOrder
            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
@@ -686,20 +691,30 @@
                productOrder.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
                productOrder.setProductModelId(salesLedgerProduct.getId());
                productOrder.setNpsNo("SC" + String.format("%08d", salesLedgerProduct.getId()));
                productOrder.setQuantity(salesLedgerProduct.getQuantity());//需求数量
                productOrder.setCompleteQuantity(BigDecimal.ZERO);//完成数量
                productOrderMapper.insert(productOrder);
                ProcessRoute processRoute = processRouteMapper.selectOne(new QueryWrapper<ProcessRoute>().lambda().eq(ProcessRoute::getProductModelId, salesLedgerProduct.getProductModelId()));
                if (processRoute != null) {
                    //新增生产订单工艺路线主表
                    ProductProcessRoute productProcessRoute = new ProductProcessRoute();
                    productProcessRoute.setProductModelId(processRoute.getProductModelId());
                    productProcessRoute.setProcessRouteCode(processRoute.getProcessRouteCode());
                    productProcessRoute.setProductOrderId(productOrder.getId());
                    productProcessRoute.setBomId(processRoute.getBomId());
                    productProcessRouteMapper.insert(productProcessRoute);
                    //新增生产订单工艺路线子表
                    List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
                    // ç”Ÿæˆå½“前日期的前缀:年月日
                    String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                    int dragSort = 1;
                    for (ProcessRouteItem processRouteItem : processRouteItems) {
                        ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
                        productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
                        productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
                        productProcessRouteItem.setRouteId(productOrder.getId());
                        productProcessRouteItem.setDragSort(dragSort);
                        productProcessRouteItem.setProductOrderId(productOrder.getId());
                        productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
                        productProcessRouteItem.setDragSort(processRouteItem.getDragSort());
                        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
                        if (insert > 0) {
                            // æŸ¥è¯¢ä»Šæ—¥å·²å­˜åœ¨çš„æœ€å¤§å·¥å•号
@@ -732,7 +747,6 @@
                            productWorkOrder.setStatus(1);
                            productWorkOrderMapper.insert(productWorkOrder);
                        }
                        dragSort++;
                    }
                    productOrder.setRouteId(processRoute.getId());
                    productOrderMapper.updateById(productOrder);
src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -14,11 +14,17 @@
        <result property="updateTime" column="update_time"/>
    </resultMap>
    <select id="pageProductOrder" resultType="com.ruoyi.production.dto.ProductOrderDto">
        select po.*,sl.sales_contract_no,sl.customer_name,slp.product_category,slp.specification_model
        select po.*,
        sl.sales_contract_no,
        sl.customer_name,
        slp.product_category,
        slp.specification_model,
        ppr.process_route_code,
        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus
        from product_order po
        left join sales_ledger sl on po.sales_ledger_id = sl.id
        left join sales_ledger_product slp on po.product_model_id = slp.id
        left join process_route pr on po.route_id = pr.id
        left join product_process_route ppr on po.id = ppr.product_order_id
        <where>
            <if test="c.npsNo != null and c.npsNo != ''">
                and po.nps_no like concat('%',#{c.npsNo},'%')
@@ -38,8 +44,7 @@
        </where>
    </select>
    <select id="productMainByOrderId" resultType="com.ruoyi.production.dto.ProductOrderDto">
        select
            po.*,
        select po.*,
            pwo.work_order_no,
            pwo.report_work,
            pwo.status,
@@ -49,6 +54,13 @@
        left join product_work_order pwo on po.id = pwo.product_order_id
        where po.id = #{c.id}
    </select>
    <select id="listProcessRoute" resultType="com.ruoyi.production.pojo.ProcessRoute">
        select pr.*
        from process_route pr
                 left join product_model pm on pr.product_model_id = pm.id
                 left join sales_ledger_product slp on pm.id = slp.product_model_id
        where slp.id = #{productModelId}
    </select>
</mapper>
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml
@@ -20,7 +20,7 @@
                 left join product_model pm on ppri.product_model_id = pm.id
                 left join product p on pm.product_id = p.id
                 left join product_process pp on pp.id = ppri.process_id
        where ppri.route_id = #{orderId}
        where ppri.product_order_id = #{orderId}
        order by ppri.drag_sort
    </select>
src/main/resources/mapper/production/ProductProcessRouteMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
<?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.ProductProcessRouteMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductProcessRoute">
        <id column="id" property="id"/>
        <result column="product_model_id" property="productModelId"/>
        <result column="description" property="description"/>
        <result column="tenant_id" property="tenantId"/>
        <result column="create_time" property="createTime"/>
        <result column="update_time" property="updateTime"/>
        <result column="bom_id" property="bomId"/>
        <result column="process_route_code" property="processRouteCode"/>
        <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
        from product_process_route ppr
                 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}
    </select>
</mapper>